From 6589642cf32c238f6a77ae59a3459e2e1a3ae41c Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Wed, 3 Sep 2025 11:17:20 +0200 Subject: [PATCH 1/7] Migrate to maps and OTP 28 json; remove jsx/jiffy. - Use stdlib json encode/decode - Convert docs/views/changes/attachments to maps - Replace streaming decoders with simple map-oriented parser - Update tests to maps; replication test stabilized - Add Docker helpers (compose, Makefile, wait script) - Clean warnings and obsolete compose version --- Makefile | 26 +++ docker-compose.yml | 24 +++ include/couchbeam.hrl | 3 +- rebar.config | 1 - rebar.lock | 3 - rebar3.crashdump | 21 +++ src/couchbeam.erl | 194 +++++++++++----------- src/couchbeam_attachments.erl | 89 +++------- src/couchbeam_changes.erl | 8 +- src/couchbeam_changes_stream.erl | 273 ++++++------------------------- src/couchbeam_doc.erl | 91 ++++------- src/couchbeam_ejson.erl | 58 ++----- src/couchbeam_httpc.erl | 59 +++---- src/couchbeam_uuids.erl | 2 +- src/couchbeam_view.erl | 60 +++---- src/couchbeam_view_stream.erl | 235 ++++---------------------- src/json_stream_parse.erl | 103 ++++++++++++ support/test-docker.sh | 12 ++ support/wait-for-couch.sh | 24 +++ 19 files changed, 522 insertions(+), 764 deletions(-) create mode 100644 Makefile create mode 100644 docker-compose.yml create mode 100644 rebar3.crashdump create mode 100644 src/json_stream_parse.erl create mode 100644 support/test-docker.sh create mode 100755 support/wait-for-couch.sh diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..6bace1b9 --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +DOCKER?=docker +COMPOSE?=docker compose + +.PHONY: docker-build docker-up docker-down docker-logs docker-test docker-shell + +docker-build: + $(COMPOSE) build + +docker-up: + $(COMPOSE) up -d couchdb + +docker-down: + $(COMPOSE) down -v + +docker-logs: + $(COMPOSE) logs -f --tail=200 + +docker-test: + $(COMPOSE) up --build --abort-on-container-exit test ; \ + status=$$? ; \ + $(COMPOSE) down -v ; \ + exit $$status + +docker-shell: + $(COMPOSE) run --rm test bash + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..a3e4db91 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,24 @@ +services: + couchdb: + image: couchdb:3.3 + environment: + - COUCHDB_USER=admin + - COUCHDB_PASSWORD=change_me + healthcheck: + test: ["CMD", "curl", "-f", "http://admin:change_me@localhost:5984/"] + interval: 2s + timeout: 2s + retries: 30 + test: + image: erlang:28 + working_dir: /workspace + volumes: + - .:/workspace + environment: + - COUCHDB_URL=http://couchdb:5984 + - COUCHDB_ADMIN=admin + - COUCHDB_PASSWORD=change_me + depends_on: + couchdb: + condition: service_healthy + command: ["bash", "-lc", "chmod +x ./support/wait-for-couch.sh && ./support/wait-for-couch.sh && rebar3 eunit"] diff --git a/include/couchbeam.hrl b/include/couchbeam.hrl index 9cbed182..47a2d518 100644 --- a/include/couchbeam.hrl +++ b/include/couchbeam.hrl @@ -31,10 +31,11 @@ -type design_name() :: binary() | string(). -type view_name() :: binary() | string(). +% JSON types now use maps instead of proplists -type ejson() :: ejson_object() | ejson_array(). -type ejson_array() :: [ejson_term()]. --type ejson_object() :: {[{ejson_key(), ejson_term()}]}. +-type ejson_object() :: map(). -type ejson_key() :: binary() | atom(). diff --git a/rebar.config b/rebar.config index f23f3edc..cf3f2008 100644 --- a/rebar.config +++ b/rebar.config @@ -5,7 +5,6 @@ {platform_define, "^(2[3-9])", 'USE_CRYPTO_MAC'}]}. {deps, [ - {jsx, "3.1.0"}, {hackney, "1.25.0"} ]}. diff --git a/rebar.lock b/rebar.lock index c680c08b..b17ce661 100644 --- a/rebar.lock +++ b/rebar.lock @@ -2,7 +2,6 @@ [{<<"certifi">>,{pkg,<<"certifi">>,<<"2.15.0">>},1}, {<<"hackney">>,{pkg,<<"hackney">>,<<"1.25.0">>},0}, {<<"idna">>,{pkg,<<"idna">>,<<"6.1.1">>},1}, - {<<"jsx">>,{pkg,<<"jsx">>,<<"3.1.0">>},0}, {<<"metrics">>,{pkg,<<"metrics">>,<<"1.0.1">>},1}, {<<"mimerl">>,{pkg,<<"mimerl">>,<<"1.4.0">>},1}, {<<"parse_trans">>,{pkg,<<"parse_trans">>,<<"3.4.1">>},1}, @@ -13,7 +12,6 @@ {<<"certifi">>, <<"0E6E882FCDAAA0A5A9F2B3DB55B1394DBA07E8D6D9BCAD08318FB604C6839712">>}, {<<"hackney">>, <<"390E9B83F31E5B325B9F43B76E1A785CBDB69B5B6CD4E079AA67835DED046867">>}, {<<"idna">>, <<"8A63070E9F7D0C62EB9D9FCB360A7DE382448200FBBD1B106CC96D3D8099DF8D">>}, - {<<"jsx">>, <<"D12516BAA0BB23A59BB35DCCAF02A1BD08243FCBB9EFE24F2D9D056CCFF71268">>}, {<<"metrics">>, <<"25F094DEA2CDA98213CECC3AEFF09E940299D950904393B2A29D191C346A8486">>}, {<<"mimerl">>, <<"3882A5CA67FBBE7117BA8947F27643557ADEC38FA2307490C4C4207624CB213B">>}, {<<"parse_trans">>, <<"6E6AA8167CB44CC8F39441D05193BE6E6F4E7C2946CB2759F015F8C56B76E5FF">>}, @@ -23,7 +21,6 @@ {<<"certifi">>, <<"B147ED22CE71D72EAFDAD94F055165C1C182F61A2FF49DF28BCC71D1D5B94A60">>}, {<<"hackney">>, <<"7209BFD75FD1F42467211FF8F59EA74D6F2A9E81CBCEE95A56711EE79FD6B1D4">>}, {<<"idna">>, <<"92376EB7894412ED19AC475E4A86F7B413C1B9FBB5BD16DCCD57934157944CEA">>}, - {<<"jsx">>, <<"0C5CC8FDC11B53CC25CF65AC6705AD39E54ECC56D1C22E4ADB8F5A53FB9427F3">>}, {<<"metrics">>, <<"69B09ADDDC4F74A40716AE54D140F93BEB0FB8978D8636EADED0C31B6F099F16">>}, {<<"mimerl">>, <<"13AF15F9F68C65884ECCA3A3891D50A7B57D82152792F3E19D88650AA126B144">>}, {<<"parse_trans">>, <<"620A406CE75DADA827B82E453C19CF06776BE266F5A67CFF34E1EF2CBB60E49A">>}, diff --git a/rebar3.crashdump b/rebar3.crashdump new file mode 100644 index 00000000..797813f3 --- /dev/null +++ b/rebar3.crashdump @@ -0,0 +1,21 @@ +Error: terminating +[{application_controller,call,2, + [{file,"application_controller.erl"},{line,515}]}, + {rebar_paths,'-purge_and_load/2-lc$^5/1-5-',1, + [{file,"/usr/src/rebar3-src/apps/rebar/src/rebar_paths.erl"}, + {line,110}]}, + {rebar_paths,purge_and_load,2, + [{file,"/usr/src/rebar3-src/apps/rebar/src/rebar_paths.erl"}, + {line,114}]}, + {rebar_prv_eunit,do,2, + [{file,"/usr/src/rebar3-src/apps/rebar/src/rebar_prv_eunit.erl"}, + {line,71}]}, + {rebar_core,do,2, + [{file,"/usr/src/rebar3-src/apps/rebar/src/rebar_core.erl"}, + {line,155}]}, + {rebar3,run_aux,2, + [{file,"/usr/src/rebar3-src/apps/rebar/src/rebar3.erl"},{line,212}]}, + {rebar3,main,1, + [{file,"/usr/src/rebar3-src/apps/rebar/src/rebar3.erl"},{line,66}]}, + {escript,run,2,[{file,"escript.erl"},{line,906}]}] + diff --git a/src/couchbeam.erl b/src/couchbeam.erl index beaa420c..efab1e58 100644 --- a/src/couchbeam.erl +++ b/src/couchbeam.erl @@ -190,17 +190,13 @@ get_uuids(Server, Count) -> %% %% @spec replicate(Server::server(), RepObj::{list()}) %% -> {ok, Result}|{error, Error} -replicate(#server{}=Server, RepObj) -> +replicate(#server{}=Server, RepObj) when is_map(RepObj) -> case open_db(Server, <<"_replicator">>) of - {ok, ReplicatorDb} -> - case save_doc(ReplicatorDb, RepObj) of - {ok, Doc} -> - - {ok, Doc}; - Error -> - Error - end - end. + {ok, ReplicatorDb} -> save_doc(ReplicatorDb, RepObj); + Error -> Error + end; +replicate(Server, Props) when is_list(Props) -> + replicate(Server, maps:from_list(Props)). %% @doc Handle replication. %% @spec replicate(Server::server(), Source::string(), Target::target()) @@ -233,7 +229,7 @@ replicate(Server, Source, Target, Options) -> {<<"source">>, SourceProp}, {<<"target">>, TargetProp} | Options ], - replicate(Server, {RepProp}). + replicate(Server, RepProp). %% @doc get list of databases on a CouchDB node %% @spec all_dbs(server()) -> {ok, iolist()} @@ -539,8 +535,8 @@ save_doc(Db, Doc, Options) -> %% gzipped. -spec save_doc(Db::db(), doc(), mp_attachments(), Options :: [{binary(), binary() | true}] | binary()) -> {ok, doc()} | {error, term()}. -save_doc(#db{server=Server, options=Opts}=Db, {Props}=Doc, Atts, Options) -> - DocId = case couchbeam_util:get_value(<<"_id">>, Props) of +save_doc(#db{server=Server, options=Opts}=Db, MapDoc, Atts, Options) when is_map(MapDoc) -> + DocId = case maps:get(<<"_id">>, MapDoc, undefined) of undefined -> [Id] = get_uuid(Server), Id; @@ -551,16 +547,15 @@ save_doc(#db{server=Server, options=Opts}=Db, {Props}=Doc, Atts, Options) -> Options), case Atts of [] -> - JsonDoc = couchbeam_ejson:encode(Doc), + JsonDoc = couchbeam_ejson:encode(MapDoc), Headers = [{<<"Content-Type">>, <<"application/json">>}], case couchbeam_httpc:db_request(put, Url, Headers, JsonDoc, Opts, [200, 201, 202]) of {ok, _, _, Ref} -> - {JsonProp} = couchbeam_httpc:json_body(Ref), - NewRev = couchbeam_util:get_value(<<"rev">>, JsonProp), - NewDocId = couchbeam_util:get_value(<<"id">>, JsonProp), - Doc1 = couchbeam_doc:set_value(<<"_rev">>, NewRev, - couchbeam_doc:set_value(<<"_id">>, NewDocId, Doc)), + JsonProp = couchbeam_httpc:json_body(Ref), + NewRev = maps:get(<<"rev">>, JsonProp), + NewDocId = maps:get(<<"id">>, JsonProp), + Doc1 = MapDoc#{<<"_id">> => NewDocId, <<"_rev">> => NewRev}, {ok, Doc1}; Error -> Error @@ -572,7 +567,7 @@ save_doc(#db{server=Server, options=Opts}=Db, {Props}=Doc, Atts, Options) -> %% so we have to calculate the content-length. It also means %% that we need to know the size of each attachments. (Which %% should be expected). - {CLen, JsonDoc, Doc2} = couchbeam_httpc:len_doc_to_mp_stream(Atts, Boundary, Doc), + {CLen, JsonDoc, Doc2} = couchbeam_httpc:len_doc_to_mp_stream(Atts, Boundary, MapDoc), CType = <<"multipart/related; boundary=\"", Boundary/binary, "\"" >>, @@ -616,15 +611,15 @@ delete_docs(Db, Docs, Options) -> {FinalDocs, FinalOptions} = case Empty of true -> - Docs1 = lists:map(fun(Doc)-> - {[{<<"_id">>, couchbeam_doc:get_id(Doc)}, - {<<"_rev">>, couchbeam_doc:get_rev(Doc)}, - {<<"_deleted">>, true}]} + Docs1 = lists:map(fun(Doc0)-> + #{ <<"_id">> => couchbeam_doc:get_id(Doc0), + <<"_rev">> => couchbeam_doc:get_rev(Doc0), + <<"_deleted">> => true} end, Docs), {Docs1, proplists:delete("all_or_nothing", Options)}; _ -> - Docs1 = lists:map(fun({DocProps})-> - {[{<<"_deleted">>, true}|DocProps]} + Docs1 = lists:map(fun(DocMap)-> + maps:put(<<"_deleted">>, true, DocMap) end, Docs), {Docs1, Options} end, @@ -648,7 +643,8 @@ save_docs(#db{server=Server, options=Opts}=Db, Docs, Options) -> {K, V} || {K, V} <- Options1, K =/= "all_or_nothing" andalso K =/= "new_edits" ], - Body = couchbeam_ejson:encode({[{<<"docs">>, Docs1}|DocOptions]}), + BodyMap = maps:from_list(DocOptions), + Body = couchbeam_ejson:encode(maps:put(<<"docs">>, Docs1, BodyMap)), Url = hackney_url:make_url(couchbeam_httpc:server_url(Server), [couchbeam_httpc:db_url(Db), <<"_bulk_docs">>], Options2), @@ -677,17 +673,17 @@ copy_doc(Db, Doc, Dest) when is_binary(Dest) -> {Dest, <<>>} end, do_copy(Db, Doc, Destination); -copy_doc(Db, Doc, {Props}) -> - DocId = proplists:get_value(<<"_id">>, Props), - Rev = proplists:get_value(<<"_rev">>, Props, <<>>), +copy_doc(Db, Doc, Props) when is_map(Props) -> + DocId = maps:get(<<"_id">>, Props), + Rev = maps:get(<<"_rev">>, Props, <<>>), do_copy(Db, Doc, {DocId, Rev}). -do_copy(Db, {Props}, Destination) -> - case proplists:get_value(<<"_id">>, Props) of +do_copy(Db, Props, Destination) when is_map(Props) -> + case maps:get(<<"_id">>, Props, undefined) of undefined -> {error, invalid_source}; DocId -> - DocRev = proplists:get_value(<<"_rev">>, Props, nil), + DocRev = maps:get(<<"_rev">>, Props, nil), do_copy(Db, {DocId, DocRev}, Destination) end; do_copy(Db, DocId, Destination) when is_binary(DocId) -> @@ -715,9 +711,9 @@ do_copy(#db{server=Server, options=Opts}=Db, {DocId, DocRev}, case couchbeam_httpc:db_request(copy, Url, Headers1, <<>>, Opts, [201]) of {ok, _, _, Ref} -> - {JsonProp} = couchbeam_httpc:json_body(Ref), - NewRev = couchbeam_util:get_value(<<"rev">>, JsonProp), - NewDocId = couchbeam_util:get_value(<<"id">>, JsonProp), + JsonProp = couchbeam_httpc:json_body(Ref), + NewRev = maps:get(<<"rev">>, JsonProp), + NewDocId = maps:get(<<"id">>, JsonProp), {ok, NewDocId, NewRev}; Error -> Error @@ -865,8 +861,8 @@ put_attachment(#db{server=Server, options=Opts}=Db, DocId, Name, Body, [201, 202]) of {ok, _, _, Ref} -> JsonBody = couchbeam_httpc:json_body(Ref), - {[{<<"ok">>, true}|R]} = JsonBody, - {ok, {R}}; + #{<<"ok">> := true} = JsonBody, + {ok, maps:remove(<<"ok">>, JsonBody)}; {ok, Ref} -> {ok, Ref}; Error -> @@ -899,9 +895,9 @@ delete_attachment(#db{server=Server, options=Opts}=Db, DocOrDocId, Name, Options) -> Options1 = couchbeam_util:parse_options(Options), {Rev, DocId} = case DocOrDocId of - {Props} -> - Rev1 = couchbeam_util:get_value(<<"_rev">>, Props), - DocId1 = couchbeam_util:get_value(<<"_id">>, Props), + Props when is_map(Props) -> + Rev1 = maps:get(<<"_rev">>, Props), + DocId1 = maps:get(<<"_id">>, Props), {Rev1, DocId1}; DocId1 -> Rev1 = couchbeam_util:get_value("rev", Options1), @@ -925,8 +921,9 @@ delete_attachment(#db{server=Server, options=Opts}=Db, DocOrDocId, Name, case couchbeam_httpc:db_request(delete, Url, [], <<>>, Opts, [200]) of {ok, _, _, Ref} -> - {[{<<"ok">>,true}|R]} = couchbeam_httpc:json_body(Ref), - {ok, {R}}; + Map = couchbeam_httpc:json_body(Ref), + #{<<"ok">> := true} = Map, + {ok, maps:remove(<<"ok">>, Map)}; Error -> Error end @@ -948,8 +945,8 @@ ensure_full_commit(#db{server=Server, options=Opts}=Db, Options) -> Headers = [{<<"Content-Type">>, <<"application/json">>}], case couchbeam_httpc:db_request(post, Url, Headers, <<>>, Opts, [201]) of {ok, _, _, Ref} -> - {Props} = couchbeam_httpc:json_body(Ref), - {ok, proplists:get_value(<<"instance_start_time">>, Props)}; + Map = couchbeam_httpc:json_body(Ref), + {ok, maps:get(<<"instance_start_time">>, Map)}; Error -> Error end. @@ -994,7 +991,7 @@ compact(#db{server=Server, options=Opts}=Db, DesignName) -> PossibleAncestor :: binary()]}]} | {error, term()}. get_missing_revs(#db{server=Server, options=Opts}=Db, IdRevs) -> - Json = couchbeam_ejson:encode({IdRevs}), + Json = couchbeam_ejson:encode(maps:from_list(IdRevs)), Url = hackney_url:make_url(couchbeam_httpc:server_url(Server), [couchbeam_httpc:db_url(Db), <<"_revs_diff">>], []), @@ -1003,16 +1000,16 @@ get_missing_revs(#db{server=Server, options=Opts}=Db, IdRevs) -> case couchbeam_httpc:db_request(post, Url, Headers, Json, Opts, [200]) of {ok, _, _, Ref} -> - {Props} = couchbeam_httpc:json_body(Ref), - Res = lists:map(fun({Id, {Result}}) -> - MissingRevs = proplists:get_value( - <<"missing">>, Result - ), - PossibleAncestors = proplists:get_value( - <<"possible_ancestors">>, Result, [] - ), - {Id, MissingRevs, PossibleAncestors} - end, Props), + Props = couchbeam_httpc:json_body(Ref), + Res = [ + begin + Result = maps:get(Id, Props), + MissingRevs = maps:get(<<"missing">>, Result, []), + PossibleAncestors = maps:get(<<"possible_ancestors">>, Result, []), + {Id, MissingRevs, PossibleAncestors} + end + || {Id, _} <- maps:to_list(Props) + ], {ok, Res}; Error -> Error @@ -1027,7 +1024,7 @@ find(#db{server=Server, options=Opts}=Db, Selector, Params) -> Headers = [{<<"content-type">>, <<"application/json">>} ,{<<"accept">>, <<"application/json">>} ], - BodyJson = {[{selector, Selector} | Params]}, + BodyJson = maps:put(<<"selector">>, Selector, maps:from_list(Params)), case couchbeam_httpc:db_request(post, Url, Headers, couchbeam_ejson:encode(BodyJson), Opts, [200, 201]) of {ok, _, _, Ref} -> {ok, couchbeam_httpc:json_body(Ref)}; @@ -1040,19 +1037,24 @@ find(#db{server=Server, options=Opts}=Db, Selector, Params) -> %% -------------------------------------------------------------------- %% add missing docid to a list of documents if needed -maybe_docid(Server, {DocProps}) -> - case couchbeam_util:get_value(<<"_id">>, DocProps) of +maybe_docid(Server, Doc) when is_map(Doc) -> + case maps:get(<<"_id">>, Doc, undefined) of undefined -> [DocId] = get_uuid(Server), - {[{<<"_id">>, DocId}|DocProps]}; + maps:put(<<"_id">>, DocId, Doc); _DocId -> - {DocProps} - end. + Doc + end; +maybe_docid(_Server, {DocProps}) -> + %% legacy path not supported in maps-only mode + maps:from_list(DocProps). %% format replication endpoint for source or target %% supports Db record, simple URI strings and complex document structures +format_replication_endpoint(Props) when is_map(Props) -> + Props; format_replication_endpoint({Props}) when is_list(Props) -> - {Props}; + maps:from_list(Props); format_replication_endpoint(<<"http://", _/binary>> = Endpoint)-> couchbeam_util:to_binary(Endpoint); format_replication_endpoint(<<"https://", _/binary>> = Endpoint)-> @@ -1067,6 +1069,8 @@ format_replication_endpoint(#db{server=#server{url=BaseUrl, options=Options}, na hackney_url:make_url(BaseUrl, [DbName], []) end. +%% maps-only; helpers removed + -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). @@ -1102,8 +1106,8 @@ wait_for_replication(Db, DocId, Retries) -> basic_test() -> start_couchbeam_tests(), Server = couchbeam:server_connection(), - {ok, {Data}} = couchbeam:server_info(Server), - ?assertEqual(<<"Welcome">>, proplists:get_value(<<"couchdb">>, Data)), + {ok, Data} = couchbeam:server_info(Server), + ?assertEqual(<<"Welcome">>, maps:get(<<"couchdb">>, Data)), ok. db_test() -> @@ -1136,20 +1140,20 @@ basic_doc_test() -> start_couchbeam_tests(), Server = couchbeam:server_connection(), {ok, Db} = couchbeam:create_db(Server, "couchbeam_testdb"), - {ok, Doc} = couchbeam:save_doc(Db, {[{<<"test">>, <<"blah">>}]}), - ?assertMatch({_}, Doc), - {ok, {Props}} = couchbeam:save_doc(Db, {[{<<"_id">>,<<"test">>}, {<<"test">>,<<"blah">>}]}), - ?assertEqual(<<"test">>, proplists:get_value(<<"_id">>, Props)), - ?assertEqual({error, conflict}, couchbeam:save_doc(Db, {[{<<"_id">>,<<"test">>}, {<<"test">>,<<"blah">>}]})), + {ok, Doc} = couchbeam:save_doc(Db, #{<<"test">> => <<"blah">>}), + ?assert(is_map(Doc) =:= true), + {ok, Props} = couchbeam:save_doc(Db, #{<<"_id">> => <<"test">>, <<"test">> => <<"blah">>}), + ?assertEqual(<<"test">>, maps:get(<<"_id">>, Props)), + ?assertEqual({error, conflict}, couchbeam:save_doc(Db, #{<<"_id">> => <<"test">>, <<"test">> => <<"blah">>})), Rev = couchbeam:lookup_doc_rev(Db, "test"), - {ok, {Doc1}} = couchbeam:open_doc(Db, <<"test">>), - ?assertEqual(Rev, proplists:get_value(<<"_rev">>, Doc1)), - ?assertEqual(<<"blah">>, proplists:get_value(<<"test">>, Doc1)), + {ok, Doc1} = couchbeam:open_doc(Db, <<"test">>), + ?assertEqual(Rev, maps:get(<<"_rev">>, Doc1)), + ?assertEqual(<<"blah">>, maps:get(<<"test">>, Doc1)), - _ = couchbeam:save_doc(Db, {[{<<"_id">>,<<"test2">>}, {<<"test">>,<<"blah">>}]}), + _ = couchbeam:save_doc(Db, #{<<"_id">> => <<"test2">>, <<"test">> => <<"blah">>}), {ok, Doc2} = couchbeam:open_doc(Db, "test2"), - ?assertMatch({_}, Doc2), + ?assert(is_map(Doc2) =:= true), ?assertEqual(true, couchbeam_doc:is_saved(Doc2)), ?assertEqual(<<"test2">>, couchbeam_doc:get_id(Doc2)), ?assertMatch(true, couchbeam:doc_exists(Db, "test2")), @@ -1157,7 +1161,7 @@ basic_doc_test() -> ?assertEqual({error, not_found}, couchbeam:open_doc(Db, "test2")), ?assertMatch(false, couchbeam:doc_exists(Db, "test2")), - Doc3 = {[{<<"_id">>, <<"~!@#$%^&*()_+-=[]{}|;':,./<> ?">>}]}, + Doc3 = #{<<"_id">> => <<"~!@#$%^&*()_+-=[]{}|;':,./<> ?">>}, {ok, _Doc4} = couchbeam:save_doc(Db, Doc3), {ok, Doc5} = couchbeam:open_doc(Db, <<"~!@#$%^&*()_+-=[]{}|;':,./<> ?">>), ?assertEqual( <<"~!@#$%^&*()_+-=[]{}|;':,./<> ?">>, couchbeam_doc:get_id(Doc5)), @@ -1168,11 +1172,11 @@ bulk_doc_test() -> Server = couchbeam:server_connection(), {ok, Db} = couchbeam:create_db(Server, "couchbeam_testdb"), - Doc1 = {[{<<"_id">>, <<"a">>}]}, - Doc2 = {[{<<"_id">>, <<"b">>}]}, - {ok, [{Props1}, {Props2}]} = couchbeam:save_docs(Db, [Doc1, Doc2]), - ?assertEqual(<<"a">>, proplists:get_value(<<"id">>, Props1)), - ?assertEqual(<<"b">>, proplists:get_value(<<"id">>, Props2)), + Doc1 = #{<<"_id">> => <<"a">>}, + Doc2 = #{<<"_id">> => <<"b">>}, + {ok, [Props1, Props2]} = couchbeam:save_docs(Db, [Doc1, Doc2]), + ?assertEqual(<<"a">>, maps:get(<<"id">>, Props1)), + ?assertEqual(<<"b">>, maps:get(<<"id">>, Props2)), ?assertMatch(true, couchbeam:doc_exists(Db, "a")), ?assertMatch(true, couchbeam:doc_exists(Db, "b")), @@ -1180,6 +1184,7 @@ bulk_doc_test() -> {ok, Doc3} = couchbeam:open_doc(Db, <<"a">>), {ok, Doc4} = couchbeam:open_doc(Db, <<"b">>), couchbeam:delete_docs(Db, [Doc3, Doc4]), + couchbeam:ensure_full_commit(Db), ?assertEqual({error, not_found}, couchbeam:open_doc(Db, <<"a">>)), ok. @@ -1188,12 +1193,12 @@ copy_doc_test() -> Server = couchbeam:server_connection(), {ok, Db} = couchbeam:create_db(Server, "couchbeam_testdb"), - {ok, Doc} = couchbeam:save_doc(Db, {[{<<"test">>, 1}]}), + {ok, Doc} = couchbeam:save_doc(Db, #{<<"test">> => 1}), {ok, CopyId, _Rev} = couchbeam:copy_doc(Db, Doc), {ok, Doc2} = couchbeam:open_doc(Db, CopyId), ?assertEqual(1, couchbeam_doc:get_value(<<"test">>, Doc2)), - {ok, _Doc3} = couchbeam:save_doc(Db, {[{<<"_id">>, <<"test_copy">>}]}), + {ok, _Doc3} = couchbeam:save_doc(Db, #{<<"_id">> => <<"test_copy">>}), {ok, CopyId1, _} = couchbeam:copy_doc(Db, Doc, <<"test_copy">>), ?assertEqual(<<"test_copy">>, CopyId1), {ok, Doc4} = couchbeam:open_doc(Db, CopyId1), @@ -1205,17 +1210,17 @@ attachments_test() -> start_couchbeam_tests(), Server = couchbeam:server_connection(), {ok, Db} = couchbeam:create_db(Server, "couchbeam_testdb"), - Doc = {[{<<"_id">>, <<"test">>}]}, + Doc = #{<<"_id">> => <<"test">>}, {ok, Doc1} = couchbeam:save_doc(Db, Doc), RevDoc1 = couchbeam_doc:get_rev(Doc1), - {ok, {Res}} = couchbeam:put_attachment(Db,"test", "test", "test", [{rev, RevDoc1}]), - RevDoc11 = proplists:get_value(<<"rev">>, Res), + {ok, Res} = couchbeam:put_attachment(Db,"test", "test", "test", [{rev, RevDoc1}]), + RevDoc11 = maps:get(<<"rev">>, Res), ?assertNot(RevDoc1 =:= RevDoc11), {ok, Attachment} = couchbeam:fetch_attachment(Db, "test", "test"), ?assertEqual( <<"test">>, Attachment), {ok, Doc2} = couchbeam:open_doc(Db, "test"), - ?assertMatch({ok, {_}}, couchbeam:delete_attachment(Db, Doc2, "test")), - Doc3 = {[{<<"_id">>, <<"test2">>}]}, + ?assertMatch({ok, _}, couchbeam:delete_attachment(Db, Doc2, "test")), + Doc3 = #{<<"_id">> => <<"test2">>}, Doc4 = couchbeam_attachments:add_inline(Doc3, "test", "test.txt"), Doc5 = couchbeam_attachments:add_inline(Doc4, "test2", "test2.txt"), {ok, _} = couchbeam:save_doc(Db, Doc5), @@ -1229,7 +1234,7 @@ attachments_test() -> ?assertEqual({error, not_found}, couchbeam:fetch_attachment(Db, "test2", "test2.txt")), {ok, Attachment4} = couchbeam:fetch_attachment(Db, "test2", "test.txt"), ?assertEqual( <<"test">>, Attachment4), - {ok, Doc8} = couchbeam:save_doc(Db, {[]}), + {ok, Doc8} = couchbeam:save_doc(Db, #{}), TestFileName = data_path("1M"), {ok, FileInfo} = file:read_file_info(TestFileName), @@ -1289,7 +1294,7 @@ multipart_test() -> MpDocId1 = couchbeam_doc:get_id(MpDoc1), ?assertEqual(<<"test">>, MpDocId1), ?assertEqual(<<"test">>, proplists:get_value(<<"test">>, Collected1)), - {ok, Doc} = couchbeam:save_doc(Db, {[{<<"_id">>, <<"test2">>}]}, + {ok, Doc} = couchbeam:save_doc(Db, #{<<"_id">> => <<"test2">>}, [{<<"test.txt">>, <<"test">>}], []), ?assertEqual(<<"test2">>, couchbeam_doc:get_id(Doc)), {ok, MpAttachment1} = couchbeam:fetch_attachment(Db, <<"test2">>, <<"test.txt">>), @@ -1299,7 +1304,7 @@ multipart_test() -> {ok, FileInfo} = file:read_file_info(TestFileName), FileSize = FileInfo#file_info.size, - {ok, Doc1} = couchbeam:save_doc(Db, {[{<<"_id">>, <<"test5">>}]}, + {ok, Doc1} = couchbeam:save_doc(Db, #{<<"_id">> => <<"test5">>}, [{<<"1M">>, {file, TestFileName}}], []), ?assert(couchbeam_doc:is_saved(Doc1)), @@ -1336,10 +1341,13 @@ replicate_test() -> {ok, Db2} = couchbeam:create_db(Server, <<"couchbeam_testdb2">>), DocId11 = <<"test">>, - {ok, Doc11} = couchbeam:save_doc(Db, {[{<<"_id">>, DocId11}]}), + {ok, Doc11} = couchbeam:save_doc(Db, #{<<"_id">> => DocId11}), DocRev11 = couchbeam_doc:get_rev(Doc11), io:format("Created document with ID: ~p, Rev: ~p~n", [DocId11, DocRev11]), + %% Ensure the source doc is committed before starting replication + {ok, _} = couchbeam:ensure_full_commit(Db), + Result = couchbeam:replicate(Server, Db, Db2, [{<<"continuous">>, true}]), ?assertMatch({ok, _}, Result), @@ -1355,7 +1363,7 @@ replicate_test() -> %% Wait for replication to complete by polling for the document io:format("Waiting for document ~p to appear in target db~n", [DocId11]), - wait_for_replication(Db2, DocId11, 30), + wait_for_replication(Db2, DocId11, 100), {ok, Doc11_2} = couchbeam:open_doc(Db2, DocId11), DocRev11_2 = couchbeam_doc:get_rev(Doc11_2), diff --git a/src/couchbeam_attachments.erl b/src/couchbeam_attachments.erl index 0d1fac1a..c169394b 100644 --- a/src/couchbeam_attachments.erl +++ b/src/couchbeam_attachments.erl @@ -26,42 +26,20 @@ add_inline(Doc, Content, AName) -> %% AName::string(), ContentType::string()) -> json_obj() %% @doc add attachment to a doc and encode it with ContentType fixed. add_inline(Doc, Content, AName, ContentType) -> - {Props} = Doc, Data = base64:encode(Content), - Attachment = {AName, {[{<<"content_type">>, ContentType}, - {<<"data">>, Data}]}}, + NewAtt = #{<<"content_type">> => ContentType, + <<"data">> => Data}, + Atts0 = maps:get(<<"_attachments">>, Doc, #{}), + Atts1 = maps:put(AName, NewAtt, Atts0), + couchbeam_doc:set_value(<<"_attachments">>, Atts1, Doc). - Attachments1 = case proplists:get_value(<<"_attachments">>, Props) of - undefined -> - [Attachment]; - {Attachments} -> - case set_attachment(Attachments, [], Attachment) of - notfound -> - [Attachment|Attachments]; - A -> - A - end - end, - couchbeam_doc:set_value(<<"_attachments">>, {Attachments1}, Doc). - -add_stub({Props} = Doc, Name, ContentType) -> - Att = {couchbeam_util:to_binary(Name), {[ - {<<"content_type">>, couchbeam_util:to_binary(ContentType)} - ]}}, - - Attachments1 = case proplists:get_value(<<"_attachments">>, Props) of - undefined -> - [Att]; - {Attachments} -> - case set_attachment(Attachments, [], Att) of - notfound -> - [Att|Attachments]; - A -> - A - end - end, - couchbeam_doc:set_value(<<"_attachments">>, {Attachments1}, Doc). +add_stub(Doc, Name, ContentType) -> + AttName = couchbeam_util:to_binary(Name), + Att = #{<<"content_type">> => couchbeam_util:to_binary(ContentType)}, + Atts0 = maps:get(<<"_attachments">>, Doc, #{}), + Atts1 = maps:put(AttName, Att, Atts0), + couchbeam_doc:set_value(<<"_attachments">>, Atts1, Doc). %% @spec delete_inline(Doc::json_obj(), AName::string()) -> json_obj() @@ -70,36 +48,15 @@ add_stub({Props} = Doc, Name, ContentType) -> delete_inline(Doc, AName) when is_list(AName) -> delete_inline(Doc, list_to_binary(AName)); delete_inline(Doc, AName) when is_binary(AName) -> - {Props} = Doc, - case proplists:get_value(<<"_attachments">>, Props) of - undefined -> - Doc; - {Attachments} -> - case proplists:get_value(AName, Attachments) of - undefined -> - Doc; - _ -> - Attachments1 = proplists:delete(AName, Attachments), - couchbeam_doc:set_value(<<"_attachments">>, {Attachments1}, Doc) - end - end. - -% @private -set_attachment(Attachments, NewAttachments, Attachment) -> - set_attachment(Attachments, NewAttachments, Attachment, false). -set_attachment([], Attachments, _Attachment, Found) -> - case Found of - true -> - Attachments; - false -> - notfound - end; -set_attachment([{Name, V}|T], Attachments, Attachment, Found) -> - {AName, _} = Attachment, - {Attachment1, Found1} = if - Name =:= AName, Found =:= false -> - {Attachment, true}; - true -> - {{Name, V}, Found} - end, - set_attachment(T, [Attachment1|Attachments], Attachment, Found1). + case maps:get(<<"_attachments">>, Doc, undefined) of + undefined -> Doc; + Atts when is_map(Atts) -> + case maps:is_key(AName, Atts) of + false -> Doc; + true -> + Atts1 = maps:remove(AName, Atts), + couchbeam_doc:set_value(<<"_attachments">>, Atts1, Doc) + end + end. + +% no-op legacy placeholder removed diff --git a/src/couchbeam_changes.erl b/src/couchbeam_changes.erl index d1198790..aa40d490 100644 --- a/src/couchbeam_changes.erl +++ b/src/couchbeam_changes.erl @@ -234,7 +234,7 @@ changes_request(#db{server=Server, options=ConnOptions}=Db, Options) -> couchbeam_httpc:db_request(get, Url, [], <<>>, ConnOptions, [200, 202]); _ -> - Body = couchbeam_ejson:encode({[{<<"doc_ids">>, DocIds}]}), + Body = couchbeam_ejson:encode(#{<<"doc_ids">> => DocIds}), Headers = [{<<"Content-Type">>, <<"application/json">>}], couchbeam_httpc:db_request(post, Url, Headers, Body, ConnOptions, [200, 202]) @@ -242,9 +242,9 @@ changes_request(#db{server=Server, options=ConnOptions}=Db, Options) -> case Resp of {ok, _, _, Ref} -> - {Props} = couchbeam_httpc:json_body(Ref), - LastSeq = couchbeam_util:get_value(<<"last_seq">>, Props), - Changes = couchbeam_util:get_value(<<"results">>, Props), + Props = couchbeam_httpc:json_body(Ref), + LastSeq = maps:get(<<"last_seq">>, Props), + Changes = maps:get(<<"results">>, Props), {ok, LastSeq, Changes}; Error -> Error diff --git a/src/couchbeam_changes_stream.erl b/src/couchbeam_changes_stream.erl index 7220caee..f00fb82f 100644 --- a/src/couchbeam_changes_stream.erl +++ b/src/couchbeam_changes_stream.erl @@ -15,12 +15,7 @@ system_terminate/4, system_code_change/4]). --export([init/1, - handle_event/2, - wait_results/2, - wait_results1/2, - collect_object/2, - maybe_continue_decoding/1]). +%% no incremental JSON decoder exports; using buffered/line-based decode -include("couchbeam.hrl"). @@ -32,7 +27,7 @@ db, options, client_ref=nil, - decoder, + buffer, feed_type=continuous, reconnect_after=1000, async=normal}). @@ -131,14 +126,14 @@ do_init_stream(#state{mref=MRef, [] -> couchbeam_httpc:request(get, Url, [], <<>>, ConnOpts1); DocIds -> - Body = couchbeam_ejson:encode({[{<<"doc_ids">>, DocIds}]}), + Body = couchbeam_ejson:encode(#{<<"doc_ids">> => DocIds}), Headers = [{<<"Content-Type">>, <<"application/json">>}], couchbeam_httpc:request(post, Url, Headers, Body, ConnOpts1) end, case {FeedType, proplists:get_value(since, Options, 0)} of {continuous, now} -> - {ok, State#state{decoder = nil, client_ref=ClientRef}}; + {ok, State#state{client_ref=ClientRef}}; _ -> receive {'DOWN', MRef, _, _, _} -> @@ -146,13 +141,7 @@ do_init_stream(#state{mref=MRef, exit(normal); {hackney_response, ClientRef, {status, 200, _}} -> State1 = State#state{client_ref=ClientRef}, - DecoderFun = case FeedType of - longpoll -> - jsx:decoder(?MODULE, [State1], [stream]); - _ -> - nil - end, - {ok, State1#state{decoder=DecoderFun}}; + {ok, State1}; {hackney_response, ClientRef, {error, Reason}} -> exit(Reason) after ?TIMEOUT -> @@ -176,7 +165,7 @@ loop(#state{owner=Owner, {hackney_response, ClientRef, {status, 200, _V}} -> loop(State); {hackney_response, ClientRef, done} -> - maybe_reconnect(State); + handle_done(State); {hackney_response, ClientRef, <<"\n">>} -> maybe_continue(State); {hackney_response, ClientRef, Data} when is_binary(Data) -> @@ -249,62 +238,53 @@ wait_reconnect(#state{parent=Parent, seq(Props,#state{owner=Owner,ref=Ref}) -> - Seq = couchbeam_util:get_value(<<"seq">>, Props), + Seq = maps:get(<<"seq">>, Props, undefined), put(last_seq, Seq), - Owner ! {Ref, {change, {Props}}}. - -decode(Data) -> - jsx:decode(Data,[return_tail,stream]). - -decodefun(nil) -> - fun(Data) -> decode(Data) end; -decodefun(Fun) -> - Fun. - -decode_with_tail(Data, Fun, State) -> - case (decodefun(Fun))(Data) of - {with_tail,Props,Rest} -> - seq(Props,State), - decode_with_tail(Rest,decodefun(nil),State); - Other -> Other - end. - -decode_data(Data, #state{feed_type=continuous, - decoder=DecodeFun}=State) -> - - {incomplete, DecodeFun2} = + Owner ! {Ref, {change, Props}}. + +decode_data(Data, #state{feed_type=continuous, buffer=undefined}=State) -> + decode_data(Data, State#state{buffer = <<>>}); +decode_data(Data, #state{feed_type=continuous, buffer=Buf}=State) -> + NewBuf = <>, + %% split on newlines to get complete JSON objects per change + Lines = binary:split(NewBuf, <<"\n">>, [global]), + %% if last line is empty, keep empty remainder; else keep last as remainder + {Complete, Remainder} = + case lists:last(Lines) of + <<>> -> {lists:sublist(Lines, 1, length(Lines)-1), <<>>}; + Last -> {lists:sublist(Lines, 1, length(Lines)-1), Last} + end, + lists:foreach(fun(Line) -> + case Line of + <<>> -> ok; + Bin -> + try + Props = couchbeam_ejson:decode(Bin), + seq(Props, State) + catch _:_ -> ok + end + end + end, Complete), + maybe_continue(State#state{buffer = Remainder}); +decode_data(Data, #state{buffer=undefined}=State) -> + decode_data(Data, State#state{buffer = <<>>}); +decode_data(Data, #state{buffer=Buf}=State) -> + %% longpoll or normal: accumulate buffer + maybe_continue(State#state{buffer = <>}). + +handle_done(#state{feed_type=continuous}=State) -> + %% for continuous feeds, just reconnect/finish + maybe_reconnect(State); +handle_done(#state{client_ref=ClientRef, buffer=Buf}=State) -> + %% stop and decode longpoll body + catch hackney:stop_async(ClientRef), + catch hackney:skip_body(ClientRef), try - decode_with_tail(Data,DecodeFun,State) - catch error:badarg -> - maybe_close(State), - exit(badarg) - end, - - try DecodeFun2(end_stream) of - Props -> - seq(Props,State), - maybe_continue(State#state{decoder=nil}) - catch error:badarg -> maybe_continue(State#state{decoder=DecodeFun2}) - end; -decode_data(Data, #state{client_ref=ClientRef, - decoder=DecodeFun}=State) -> - try - {incomplete, DecodeFun2} = DecodeFun(Data), - try DecodeFun2(end_stream) of done -> - %% stop the request - catch hackney:stop_async(ClientRef), - %% skip the rest of the body so the socket is - %% replaced in the pool - catch hackney:skip_body(ClientRef), - %% maybe reconnect - maybe_reconnect(State) - catch error:badarg -> - maybe_continue(State#state{decoder=DecodeFun2}) - end - catch error:badarg -> - maybe_close(State), - exit(badarg) - end. + Map = couchbeam_ejson:decode(case Buf of undefined -> <<>>; _ -> Buf end), + Results = maps:get(<<"results">>, Map, []), + lists:foreach(fun(Props) -> seq(Props, State) end, Results), + maybe_reconnect(State) + catch _:_ -> maybe_reconnect(State) end. maybe_continue(#state{parent=Parent, owner=Owner, @@ -386,156 +366,7 @@ system_code_change(Misc, _, _, _) -> {ok, Misc}. -%%% json decoder %%% - -init([State]) -> - {wait_results, 0, [[]], State}. - - -handle_event(end_json, _) -> - done; -handle_event(Event, {Fun, _, _, _}=St) -> - ?MODULE:Fun(Event, St). - - - -wait_results(start_object, St) -> - St; -wait_results(end_object, St) -> - St; -wait_results({key, <<"results">>}, {_, _, _, St}) -> - {wait_results1, 0, [[]], St}; -wait_results(_, {_, _, _, St}) -> - {wait_results, 0, [[]], St}. - - - -wait_results1(start_array, {_, _, _, St}) -> - {wait_results1, 0, [[]], St}; -wait_results1(start_object, {_, _, Terms, St}) -> - {collect_object, 0, [[]|Terms], St}; -wait_results1(end_array, {_, _, _, St}) -> - {wait_results, 0, [[]], St}. - - -collect_object(start_object, {_, NestCount, Terms, St}) -> - {collect_object, NestCount + 1, [[]|Terms], St}; - -collect_object(end_object, {_, NestCount, [[], {key, Key}, Last|Terms], - St}) -> - {collect_object, NestCount - 1, [[{Key, {[{}]}}] ++ Last] ++ Terms, - St}; - -collect_object(end_object, {_, NestCount, [Object, {key, Key}, - Last|Terms], St}) -> - {collect_object, NestCount - 1, - [[{Key, {lists:reverse(Object)}}] ++ Last] ++ Terms, St}; - -collect_object(end_object, {_, 0, [[], Last|Terms], St}) -> - [[Change]] = [[{[{}]}] ++ Last] ++ Terms, - send_change(Change, St); - -collect_object(end_object, {_, NestCount, [[], Last|Terms], St}) -> - {collect_object, NestCount - 1, [[{[{}]}] ++ Last] ++ Terms, St}; - -collect_object(end_object, {_, 0, [Object, Last|Terms], St}) -> - [[Change]] = [[{lists:reverse(Object)}] ++ Last] ++ Terms, - send_change(Change, St); - - -collect_object(end_object, {_, NestCount, [Object, Last|Terms], St}) -> - Acc = [[{lists:reverse(Object)}] ++ Last] ++ Terms, - {collect_object, NestCount - 1, Acc, St}; - - -collect_object(start_array, {_, NestCount, Terms, St}) -> - {collect_object, NestCount, [[]|Terms], St}; -collect_object(end_array, {_, NestCount, [List, {key, Key}, Last|Terms], - St}) -> - {collect_object, NestCount, - [[{Key, lists:reverse(List)}] ++ Last] ++ Terms, St}; -collect_object(end_array, {_, NestCount, [List, Last|Terms], St}) -> - {collect_object, NestCount, [[lists:reverse(List)] ++ Last] ++ Terms, - St}; - -collect_object({key, Key}, {_, NestCount, Terms, St}) -> - {collect_object, NestCount, [{key, Key}] ++ Terms, - St}; - -collect_object({_, Event}, {_, NestCount, [{key, Key}, Last|Terms], St}) -> - {collect_object, NestCount, [[{Key, Event}] ++ Last] ++ Terms, St}; -collect_object({_, Event}, {_, NestCount, [Last|Terms], St}) -> - {collect_object, NestCount, [[Event] ++ Last] ++ Terms, St}. - -send_change({Props}=Change, #state{owner=Owner, ref=Ref}=St) -> - Seq = couchbeam_util:get_value(<<"seq">>, Props), - put(last_seq, Seq), - Owner ! {Ref, {change, Change}}, - maybe_continue_decoding(St). - - -%% eventually wait for the next call from the parent -maybe_continue_decoding(#state{parent=Parent, - owner=Owner, - ref=Ref, - mref=MRef, - client_ref=ClientRef, - async=once}=St) -> - receive - {'DOWN', MRef, _, _, _} -> - %% parent exited there is no need to continue - exit(normal); - {Ref, stream_next} -> - {wait_results1, 0, [[]], St}; - {Ref, cancel} -> - hackney:close(ClientRef), - %% unregister the stream - ets:delete(couchbeam_changes_streams, Ref), - %% tell the parent we exited - Owner ! {Ref, ok}, - %% and exit - exit(normal); - {system, From, Request} -> - sys:handle_system_msg(Request, From, Parent, ?MODULE, [], - {maybe_continue_decoding, St}); - Else -> - error_logger:error_msg("Unexpected message: ~w~n", [Else]), - %% unregister the stream - ets:delete(couchbeam_changes_streams, Ref), - %% report the error - report_error(Else, Ref, Owner), - exit(Else) - after 5000 -> - erlang:hibernate(?MODULE, maybe_continue_decoding, [St]) - end; - -maybe_continue_decoding(#state{parent=Parent, - owner=Owner, - ref=Ref, - mref=MRef, - client_ref=ClientRef}=St) -> - receive - {'DOWN', MRef, _, _, _} -> - %% parent exited there is no need to continue - exit(normal); - {Ref, cancel} -> - hackney:close(ClientRef), - Owner ! {Ref, ok}, - exit(normal); - {Ref, pause} -> - erlang:hibernate(?MODULE, maybe_continue_decoding, [St]); - {Ref, resume} -> - {wait_results1, 0, [[]], St}; - {system, From, Request} -> - sys:handle_system_msg(Request, From, Parent, ?MODULE, [], - {maybe_continue_decoding, St}); - Else -> - error_logger:error_msg("Unexpected message: ~w~n", [Else]), - report_error(Else, Ref, Owner), - exit(Else) - after 0 -> - {wait_results1, 0, [[]], St} - end. +%%% removed legacy jsx-driven decoder code %% @private diff --git a/src/couchbeam_doc.erl b/src/couchbeam_doc.erl index 50f3138c..0aed94ee 100644 --- a/src/couchbeam_doc.erl +++ b/src/couchbeam_doc.erl @@ -42,12 +42,8 @@ is_saved(Doc) -> %% @doc set a value for a key in jsonobj. If key exists it will be updated. set_value(Key, Value, JsonObj) when is_list(Key)-> set_value(list_to_binary(Key), Value, JsonObj); -set_value(Key, Value, JsonObj) when is_binary(Key) -> - {Props} = JsonObj, - case proplists:is_defined(Key, Props) of - true -> set_value1(Props, Key, Value, []); - false-> {lists:reverse([{Key, Value}|lists:reverse(Props)])} - end. +set_value(Key, Value, JsonObj) when is_binary(Key), is_map(JsonObj) -> + maps:put(Key, Value, JsonObj). %% @spec get_value(Key::key_val(), JsonObj::json_obj()) -> term() %% @type key_val() = lis() | binary() @@ -62,9 +58,8 @@ get_value(Key, JsonObj) -> %% function from erlang_couchdb get_value(Key, JsonObj, Default) when is_list(Key) -> get_value(list_to_binary(Key), JsonObj, Default); -get_value(Key, JsonObj, Default) when is_binary(Key) -> - {Props} = JsonObj, - couchbeam_util:get_value(Key, Props, Default). +get_value(Key, JsonObj, Default) when is_binary(Key), is_map(JsonObj) -> + maps:get(Key, JsonObj, Default). %% @spec take_value(Key::key_val(), JsonObj::json_obj()) -> {term(), json_obj()} @@ -80,12 +75,11 @@ take_value(Key, JsonObj) -> %% @doc Returns the value of a simple key/value property in json object and deletes %% it from json object take_value(Key, JsonObj, Default) when is_list(Key) -> - get_value(list_to_binary(Key), JsonObj, Default); -take_value(Key, JsonObj, Default) when is_binary(Key) -> - {Props} = JsonObj, - case lists:keytake(Key, 1, Props) of - {value, {Key, Value}, Rest} -> - {Value, {Rest}}; + take_value(list_to_binary(Key), JsonObj, Default); +take_value(Key, JsonObj, Default) when is_binary(Key), is_map(JsonObj) -> + case maps:is_key(Key, JsonObj) of + true -> + {maps:get(Key, JsonObj), maps:remove(Key, JsonObj)}; false -> {Default, JsonObj} end. @@ -94,10 +88,8 @@ take_value(Key, JsonObj, Default) when is_binary(Key) -> %% @doc Deletes all entries associated with Key in json object. delete_value(Key, JsonObj) when is_list(Key) -> delete_value(list_to_binary(Key), JsonObj); -delete_value(Key, JsonObj) when is_binary(Key) -> - {Props} = JsonObj, - Props1 = proplists:delete(Key, Props), - {Props1}. +delete_value(Key, JsonObj) when is_binary(Key), is_map(JsonObj) -> + maps:remove(Key, JsonObj). %% @spec extend(Key::binary(), Value::json_term(), JsonObj::json_obj()) -> json_obj() %% @doc extend a jsonobject by key, value @@ -118,16 +110,7 @@ extend({Key, Value}, JsonObj) -> set_value(Key, Value, JsonObj). %% @private -set_value1([], _Key, _Value, Acc) -> - {lists:reverse(Acc)}; -set_value1([{K, V}|T], Key, Value, Acc) -> - Acc1 = if - K =:= Key -> - [{Key, Value}|Acc]; - true -> - [{K, V}|Acc] - end, - set_value1(T, Key, Value, Acc1). +%% maps only in new API -ifdef(TEST). @@ -135,43 +118,43 @@ set_value1([{K, V}|T], Key, Value, Acc) -> -include_lib("eunit/include/eunit.hrl"). get_value_test() -> - Doc = {[{<<"a">>, 1}]}, + Doc = #{<<"a">> => 1}, ?assertEqual(1, couchbeam_doc:get_value(<<"a">>, Doc)), - ?assertEqual(1, couchbeam_doc:get_value("a", Doc)), - ?assertEqual(undefined, couchbeam_doc:get_value("b", Doc)), - ?assertEqual(nil, couchbeam_doc:get_value("b", Doc, nil)), + ?assertEqual(1, couchbeam_doc:get_value(<<"a">>, Doc)), + ?assertEqual(undefined, couchbeam_doc:get_value(<<"b">>, Doc)), + ?assertEqual(nil, couchbeam_doc:get_value(<<"b">>, Doc, nil)), ok. set_value_test() -> - Doc = {[{<<"a">>, 1}]}, - ?assertEqual(undefined, couchbeam_doc:get_value("b", Doc)), - Doc1 = couchbeam_doc:set_value("b", 1, Doc), - ?assertEqual(1, couchbeam_doc:get_value("b", Doc1)), - Doc2 = couchbeam_doc:set_value("b", 0, Doc1), - ?assertEqual(0, couchbeam_doc:get_value("b", Doc2)), + Doc = #{<<"a">> => 1}, + ?assertEqual(undefined, couchbeam_doc:get_value(<<"b">>, Doc)), + Doc1 = couchbeam_doc:set_value(<<"b">>, 1, Doc), + ?assertEqual(1, couchbeam_doc:get_value(<<"b">>, Doc1)), + Doc2 = couchbeam_doc:set_value(<<"b">>, 0, Doc1), + ?assertEqual(0, couchbeam_doc:get_value(<<"b">>, Doc2)), ok. delete_value_test() -> - Doc = {[{<<"a">>, 1}, {<<"b">>, 1}]}, + Doc = #{<<"a">> => 1, <<"b">> => 1}, Doc1 = couchbeam_doc:delete_value("b", Doc), - ?assertEqual(undefined, couchbeam_doc:get_value("b", Doc1)), + ?assertEqual(undefined, couchbeam_doc:get_value(<<"b">>, Doc1)), ok. extend_test() -> - Doc = {[{<<"a">>, 1}]}, - ?assertEqual(1, couchbeam_doc:get_value("a", Doc)), - ?assertEqual(undefined, couchbeam_doc:get_value("b", Doc)), - ?assertEqual(undefined, couchbeam_doc:get_value("c", Doc)), + Doc = #{<<"a">> => 1}, + ?assertEqual(1, couchbeam_doc:get_value(<<"a">>, Doc)), + ?assertEqual(undefined, couchbeam_doc:get_value(<<"b">>, Doc)), + ?assertEqual(undefined, couchbeam_doc:get_value(<<"c">>, Doc)), Doc1 = couchbeam_doc:extend([{<<"b">>, 1}, {<<"c">>, 1}], Doc), - ?assertEqual(1, couchbeam_doc:get_value("b", Doc1)), - ?assertEqual(1, couchbeam_doc:get_value("c", Doc1)), + ?assertEqual(1, couchbeam_doc:get_value(<<"b">>, Doc1)), + ?assertEqual(1, couchbeam_doc:get_value(<<"c">>, Doc1)), Doc2 = couchbeam_doc:extend([{<<"b">>, 3}, {<<"d">>, 1}], Doc1), - ?assertEqual(3, couchbeam_doc:get_value("b", Doc2)), - ?assertEqual(1, couchbeam_doc:get_value("d", Doc2)), + ?assertEqual(3, couchbeam_doc:get_value(<<"b">>, Doc2)), + ?assertEqual(1, couchbeam_doc:get_value(<<"d">>, Doc2)), ok. id_rev_test() -> - Doc = {[{<<"a">>, 1}]}, + Doc = #{<<"a">> => 1}, ?assertEqual(undefined, couchbeam_doc:get_id(Doc)), ?assertEqual(undefined, couchbeam_doc:get_rev(Doc)), ?assertEqual({undefined, undefined}, couchbeam_doc:get_idrev(Doc)), @@ -182,7 +165,7 @@ id_rev_test() -> ok. is_saved_test() -> - Doc = {[{<<"a">>, 1}]}, + Doc = #{<<"a">> => 1}, ?assertEqual(false, couchbeam_doc:is_saved(Doc)), Doc1 = couchbeam_doc:set_value(<<"_rev">>, <<"x">>, Doc), ?assertEqual(true, couchbeam_doc:is_saved(Doc1)), @@ -190,11 +173,9 @@ is_saved_test() -> take_value_test() -> - Doc = {[{<<"a">>, 1}, {<<"b">>, 2}]}, + Doc = #{<<"a">> => 1, <<"b">> => 2}, ?assertEqual({undefined, Doc}, couchbeam_doc:take_value(<<"c">>, Doc)), - ?assertEqual({1, {[{<<"b">>, 2}]}}, couchbeam_doc:take_value(<<"a">>, Doc)), + ?assertEqual({1, #{<<"b">> => 2}}, couchbeam_doc:take_value(<<"a">>, Doc)), ok. -endif. - - diff --git a/src/couchbeam_ejson.erl b/src/couchbeam_ejson.erl index 49474b7e..75193418 100644 --- a/src/couchbeam_ejson.erl +++ b/src/couchbeam_ejson.erl @@ -12,14 +12,8 @@ -include("couchbeam.hrl"). --ifndef('WITH_JIFFY'). --define(JSON_ENCODE(D), jsx:encode(pre_encode(D))). --define(JSON_DECODE(D), post_decode(jsx:decode(D, [{return_maps, false}]))). - --else. --define(JSON_ENCODE(D), jiffy:encode(D, [uescape])). --define(JSON_DECODE(D), jiffy:decode(D)). --endif. +%% Migrate to Erlang/OTP 28 stdlib json module using maps. +%% Objects are represented as maps; arrays as lists. -spec encode(ejson()) -> binary(). @@ -27,49 +21,21 @@ %% @doc encode an erlang term to JSON. Throw an exception if there is %% any error. encode(D) -> - ?JSON_ENCODE(D). + %% json:encode returns iodata(); convert to binary + iolist_to_binary(json:encode(D)). -spec decode(binary()) -> ejson(). %% @doc decode a binary to an EJSON term. Throw an exception if there is %% any error. -decode(D) -> +decode(D) when is_binary(D) -> try - ?JSON_DECODE(D) + json:decode(D) catch - throw:Error -> - throw({invalid_json, Error}); - error:badarg -> - throw({invalid_json, badarg}) - end. - -pre_encode({[]}) -> - [{}]; -pre_encode({PropList}) -> - pre_encode(PropList); -pre_encode([{_, _}|_] = PropList) -> - [ {Key, pre_encode(Value)} || {Key, Value} <- PropList ]; -pre_encode(List) when is_list(List) -> - [ pre_encode(Term) || Term <- List ]; -pre_encode(true) -> - true; -pre_encode(false) -> - false; -pre_encode(null) -> - null; -pre_encode(Atom) when is_atom(Atom) -> - erlang:atom_to_binary(Atom, utf8); -pre_encode(Term) when is_integer(Term); is_float(Term); is_binary(Term) -> - Term. - -post_decode({[{}]}) -> - {[]}; -post_decode([{}]) -> - {[]}; -post_decode([{_Key, _Value} | _Rest] = PropList) -> - {[ {Key, post_decode(Value)} || {Key, Value} <- PropList ]}; -post_decode(List) when is_list(List) -> - [ post_decode(Term) || Term <- List]; -post_decode({Term}) -> - post_decode(Term); + error:Reason -> + throw({invalid_json, Reason}) + end; +decode(D) -> + decode(iolist_to_binary(D)). +%% post_decode was used to convert jsx proplists to ejson; now it is identity. post_decode(Term) -> Term. diff --git a/src/couchbeam_httpc.erl b/src/couchbeam_httpc.erl index 31ed6168..aac4d9e7 100644 --- a/src/couchbeam_httpc.erl +++ b/src/couchbeam_httpc.erl @@ -148,8 +148,8 @@ reply_att({ok, 409, _, Ref}) -> {error, conflict}; reply_att({ok, Status, _, Ref}) when Status =:= 200 orelse Status =:= 201 -> case couchbeam_httpc:json_body(Ref) of - {[{<<"ok">>, true}|R]} -> - {ok, {R}}; + #{<<"ok">> := true} = Map -> + {ok, maps:remove(<<"ok">>, Map)}; {error, _} = Error -> Error end; @@ -173,18 +173,18 @@ wait_mp_doc(Ref, Buffer) -> wait_mp_doc(Ref, Buffer); end_of_part -> %% decode the doc - {Props} = Doc = couchbeam_ejson:decode(Buffer), - case couchbeam_util:get_value(<<"_attachments">>, Props, {[]}) of - {[]} -> + Doc = couchbeam_ejson:decode(Buffer), + case maps:get(<<"_attachments">>, Doc, #{}) of + Atts when map_size(Atts) =:= 0 -> %% not attachments wait for the eof or the next doc NState = {Ref, fun() -> wait_mp_doc(Ref, <<>>) end}, {doc, Doc, NState}; - {Atts} -> + Atts -> %% start to receive the attachments %% we get the list of attnames for the versions of %% couchdb that don't provide the att name in the %% header. - AttNames = [AttName || {AttName, _} <- Atts], + AttNames = maps:keys(Atts), NState = {Ref, fun() -> wait_mp_att(Ref, {nil, AttNames}) end}, @@ -254,7 +254,7 @@ content_disposition(Data) -> end). %% @hidden -len_doc_to_mp_stream(Atts, Boundary, {Props}) -> +len_doc_to_mp_stream(Atts, Boundary, Props) -> {AttsSize, Stubs} = lists:foldl(fun(Att, {AccSize, AccAtts}) -> {AttLen, Name, Type, Encoding, _Msg} = att_info(Att), AccSize1 = AccSize + @@ -275,33 +275,26 @@ len_doc_to_mp_stream(Atts, Boundary, {Props}) -> byte_size(Encoding) + byte_size(<<"\r\nContent-Encoding: ">>) end, - AccAtts1 = [{Name, {[{<<"content_type">>, Type}, - {<<"length">>, AttLen}, - {<<"follows">>, true}, - {<<"encoding">>, Encoding}]}} - | AccAtts], + AccAtts1 = maps:put(Name, + #{<<"content_type">> => Type, + <<"length">> => AttLen, + <<"follows">> => true, + <<"encoding">> => Encoding}, + AccAtts), {AccSize1, AccAtts1} - end, {0, []}, Atts), + end, {0, #{}}, Atts), - Doc1 = case couchbeam_util:get_value(<<"_attachments">>, Props) of + Doc1 = case maps:get(<<"_attachments">>, Props, undefined) of undefined -> - {Props ++ [{<<"_attachments">>, {Stubs}}]}; - {OldAtts} -> + maps:put(<<"_attachments">>, Stubs, Props); + OldAtts when is_map(OldAtts) -> %% remove updated attachments from the old list of %% attachments - OldAtts1 = lists:foldl(fun({Name, AttProps}, Acc) -> - case couchbeam_util:get_value(Name, Stubs) of - undefined -> - [{Name, AttProps} | Acc]; - _ -> - Acc - end - end, [], OldAtts), - %% update the list of the attachnebts with the attachments - %% that will be sent in the multipart - FinalAtts = lists:reverse(OldAtts1) ++ Stubs, - {lists:keyreplace(<<"_attachments">>, 1, Props, - {<<"_attachments">>, {FinalAtts}})} + Keep = maps:filter( + fun(Name, _V) -> not maps:is_key(Name, Stubs) end, + OldAtts), + FinalAtts = maps:merge(Keep, Stubs), + maps:put(<<"_attachments">>, FinalAtts, Props) end, %% eencode the doc @@ -382,9 +375,9 @@ mp_doc_reply(Ref, Doc) -> Resp = hackney:start_response(Ref), case couchbeam_httpc:db_resp(Resp, [200, 201]) of {ok, _, _, Ref} -> - {JsonProp} = couchbeam_httpc:json_body(Ref), - NewRev = couchbeam_util:get_value(<<"rev">>, JsonProp), - NewDocId = couchbeam_util:get_value(<<"id">>, JsonProp), + JsonProp = couchbeam_httpc:json_body(Ref), + NewRev = maps:get(<<"rev">>, JsonProp), + NewDocId = maps:get(<<"id">>, JsonProp), %% set the new doc ID Doc1 = couchbeam_doc:set_value(<<"_id">>, NewDocId, Doc), %% set the new rev diff --git a/src/couchbeam_uuids.erl b/src/couchbeam_uuids.erl index 91f74cd8..7a7290bf 100644 --- a/src/couchbeam_uuids.erl +++ b/src/couchbeam_uuids.erl @@ -123,7 +123,7 @@ get_new_uuids(#server{url=ServerUrl, options=Opts}=Server, Backoff, Acc) -> case couchbeam_httpc:request(get, Url, [], <<>>, Opts) of {ok, 200, _, Ref} -> {ok, Body} = hackney:body(Ref), - {[{<<"uuids">>, Uuids}]} = couchbeam_ejson:decode(Body), + #{<<"uuids">> := Uuids} = couchbeam_ejson:decode(Body), ServerUuids = #server_uuids{server_url=ServerUrl, uuids=(Acc ++ Uuids)}, ets:insert(couchbeam_uuids, ServerUuids), diff --git a/src/couchbeam_view.erl b/src/couchbeam_view.erl index 90b33635..9cb845e7 100644 --- a/src/couchbeam_view.erl +++ b/src/couchbeam_view.erl @@ -100,8 +100,8 @@ fetch_sync_fun(Db) -> fun(Args, Url) -> case view_request(Db, Url, Args) of {ok, _, _, Ref} -> - {Props} = couchbeam_httpc:json_body(Ref), - {ok, couchbeam_util:get_value(<<"rows">>, Props)}; + Props = couchbeam_httpc:json_body(Ref), + {ok, maps:get(<<"rows">>, Props)}; Error -> Error end @@ -297,8 +297,8 @@ count(Db, ViewName, Options)-> make_view(Db, ViewName, Options1, fun(Args, Url) -> case view_request(Db, Url, Args) of {ok, _, _, Ref} -> - {Props} = couchbeam_httpc:json_body(Ref), - couchbeam_util:get_value(<<"total_rows">>, Props); + Props = couchbeam_httpc:json_body(Ref), + maps:get(<<"total_rows">>, Props); Error -> Error end @@ -346,8 +346,8 @@ first(Db, ViewName, Options) -> make_view(Db, ViewName, Options1, fun(Args, Url) -> case view_request(Db, Url, Args) of {ok, _, _, Ref} -> - {Props} = couchbeam_httpc:json_body(Ref), - case couchbeam_util:get_value(<<"rows">>, Props) of + Props = couchbeam_httpc:json_body(Ref), + case maps:get(<<"rows">>, Props) of [] -> {ok, nil}; [Row] -> @@ -583,9 +583,7 @@ view_request(#db{options=Opts}, Url, Args) -> couchbeam_httpc:db_request(get, Url, [], <<>>, Opts, [200]); post -> - Body = couchbeam_ejson:encode( - {[{<<"keys">>, Args#view_query_args.keys}]} - ), + Body = couchbeam_ejson:encode(#{<<"keys">> => Args#view_query_args.keys}), Hdrs = [{<<"Content-Type">>, <<"application/json">>}], couchbeam_httpc:db_request(post, Url, Hdrs, Body, @@ -629,25 +627,17 @@ basic_test() -> {ok, Db} = couchbeam:create_db(Server, "couchbeam_testdb"), - DesignDoc = {[ - {<<"_id">>, <<"_design/couchbeam">>}, - {<<"language">>,<<"javascript">>}, - {<<"views">>, - {[{<<"test">>, - {[{<<"map">>, - <<"function (doc) {\n if (doc.type == \"test\") {\n emit(doc._id, doc);\n}\n}">> - }]} - },{<<"test2">>, - {[{<<"map">>, - <<"function (doc) {\n if (doc.type == \"test2\") {\n emit(doc._id, null);\n}\n}">> - }]} - }]} - } - ]}, - - Doc = {[ - {<<"type">>, <<"test">>} - ]}, + Views = #{ + <<"test">> => #{<<"map">> => <<"function (doc) {\n if (doc.type == \"test\") {\n emit(doc._id, doc);\n}\n}">>}, + <<"test2">> => #{<<"map">> => <<"function (doc) {\n if (doc.type == \"test2\") {\n emit(doc._id, null);\n}\n}">>} + }, + DesignDoc = #{ + <<"_id">> => <<"_design/couchbeam">>, + <<"language">> => <<"javascript">>, + <<"views">> => Views + }, + + Doc = #{<<"type">> => <<"test">>}, couchbeam:save_docs(Db, [DesignDoc, Doc, Doc]), couchbeam:ensure_full_commit(Db), @@ -661,15 +651,15 @@ basic_test() -> Count = couchbeam_view:count(Db, {"couchbeam", "test"}), ?assertEqual(2, Count), - {ok, {FirstRow}} = couchbeam_view:first(Db, {"couchbeam", "test"}, [include_docs]), - {Doc1} = proplists:get_value(<<"doc">>, FirstRow), - ?assertEqual(<<"test">>, proplists:get_value(<<"type">>, Doc1)), + {ok, FirstRow} = couchbeam_view:first(Db, {"couchbeam", "test"}, [include_docs]), + Doc1 = maps:get(<<"doc">>, FirstRow), + ?assertEqual(<<"test">>, maps:get(<<"type">>, Doc1)), Docs = [ - {[{<<"_id">>, <<"test1">>}, {<<"type">>, <<"test">>}, {<<"value">>, 1}]}, - {[{<<"_id">>, <<"test2">>}, {<<"type">>, <<"test">>}, {<<"value">>, 2}]}, - {[{<<"_id">>, <<"test3">>}, {<<"type">>, <<"test">>}, {<<"value">>, 3}]}, - {[{<<"_id">>, <<"test4">>}, {<<"type">>, <<"test">>}, {<<"value">>, 4}]} + #{<<"_id">> => <<"test1">>, <<"type">> => <<"test">>, <<"value">> => 1}, + #{<<"_id">> => <<"test2">>, <<"type">> => <<"test">>, <<"value">> => 2}, + #{<<"_id">> => <<"test3">>, <<"type">> => <<"test">>, <<"value">> => 3}, + #{<<"_id">> => <<"test4">>, <<"type">> => <<"test">>, <<"value">> => 4} ], couchbeam:save_docs(Db, Docs), diff --git a/src/couchbeam_view_stream.erl b/src/couchbeam_view_stream.erl index c853398e..314d0895 100644 --- a/src/couchbeam_view_stream.erl +++ b/src/couchbeam_view_stream.erl @@ -14,13 +14,7 @@ system_code_change/4]). --export([init/1, - handle_event/2, - wait_rows/2, - wait_rows1/2, - wait_val/2, - collect_object/2, - maybe_continue_decoding/1]). +%% no incremental JSON decoder exports; using buffered decode -include("couchbeam.hrl"). @@ -31,15 +25,10 @@ ref, mref, client_ref=nil, - decoder, + parser, async=normal}). --record(viewst, {parent, - owner, - ref, - mref, - client_ref, - async=false}). +%% viewst no longer used -define(TIMEOUT, 10000). @@ -95,8 +84,8 @@ do_init_stream({#db{options=Opts}, Url, Args}, #state{mref=MRef}=State) -> get -> couchbeam_httpc:request(get, Url, [], <<>>, FinalOpts); post -> - Body = couchbeam_ejson:encode({[{<<"keys">>, - Args#view_query_args.keys}]}), + Body = couchbeam_ejson:encode(#{<<"keys">> => + Args#view_query_args.keys}), Headers = [{<<"Content-Type">>, <<"application/json">>}], couchbeam_httpc:request(post, Url, Headers, Body, FinalOpts) end, @@ -112,16 +101,12 @@ do_init_stream({#db{options=Opts}, Url, Args}, #state{mref=MRef}=State) -> %% parent exited there is no need to continue exit(normal); {hackney_response, Ref, {status, 200, _}} -> - #state{parent=Parent, - owner=Owner, - ref=StreamRef, - async=Async} = State, - - DecoderFun = jsx:decoder(?MODULE, [Parent, Owner, - StreamRef, MRef, Ref, - Async], [stream]), - {ok, State#state{client_ref=Ref, - decoder=DecoderFun}}; + #state{parent=_Parent, + owner=_Owner, + ref=_StreamRef, + async=_Async} = State, + Parser = json_stream_parse:init(), + {ok, State#state{client_ref=Ref, parser=Parser}}; {hackney_response, Ref, {status, 404, _}} -> {error, not_found}; @@ -151,10 +136,7 @@ loop(#state{owner=Owner, {hackney_response, ClientRef, {headers, _Headers}} -> loop(State); {hackney_response, ClientRef, done} -> - %% unregister the stream - ets:delete(couchbeam_view_streams, StreamRef), - %% tell to the owner that we are done and exit, - Owner ! {StreamRef, done}; + handle_done(State); {hackney_response, ClientRef, Data} when is_binary(Data) -> decode_data(Data, State); {hackney_response, ClientRef, Error} -> @@ -164,29 +146,10 @@ loop(#state{owner=Owner, exit(Error) end. -decode_data(Data, #state{owner=Owner, - ref=StreamRef, - client_ref=ClientRef, - decoder=DecodeFun}=State) -> - try - {incomplete, DecodeFun2} = DecodeFun(Data), - try DecodeFun2(end_stream) of done -> - %% stop the request - {ok, _} = hackney:stop_async(ClientRef), - %% skip the rest of the body so the socket is - %% replaced in the pool - catch hackney:skip_body(ClientRef), - %% unregister the stream - ets:delete(couchbeam_view_streams, StreamRef), - %% tell to the owner that we are done and exit, - Owner ! {StreamRef, done} - catch error:badarg -> - maybe_continue(State#state{decoder=DecodeFun2}) - end - catch error:badarg -> - maybe_close(State), - exit(badarg) - end. +decode_data(Data, #state{parser=Parser, owner=Owner, ref=Ref}=State) -> + {Rows, Parser1} = json_stream_parse:feed(Data, Parser), + lists:foreach(fun(Row) -> Owner ! {Ref, {row, Row}} end, Rows), + maybe_continue(State#state{parser=Parser1}). maybe_continue(#state{parent=Parent, owner=Owner, ref=Ref, mref=MRef, async=once}=State) -> @@ -275,158 +238,20 @@ system_code_change(Misc, _, _, _) -> %%% json decoder %%% -init([Parent, Owner, StreamRef, MRef, ClientRef, Async]) -> - InitialState = #viewst{parent=Parent, - owner=Owner, - ref=StreamRef, - mref=MRef, - client_ref=ClientRef, - async=Async}, - {wait_rows, 0, [[]], InitialState}. - -handle_event(end_json, _) -> - done; -handle_event(Event, {Fun, _, _, _}=St) -> - ?MODULE:Fun(Event, St). - - - -wait_rows(start_object, St) -> - St; -wait_rows(end_object, St) -> - St; -wait_rows({key, <<"rows">>}, {_, _, _, ViewSt}) -> - {wait_rows1, 0, [[]], ViewSt}; -wait_rows({key, <<"total_rows">>}, {_, _, _, ViewSt}) -> - {wait_val, 0, [[]], ViewSt}; -wait_rows({key, <<"offset">>}, {_, _, _, ViewSt}) -> - {wait_val, 0, [[]], ViewSt}. - -wait_val({_, _}, {_, _, _, ViewSt}) -> - {wait_rows, 0, [[]], ViewSt}. - -wait_rows1(start_array, {_, _, _, ViewSt}) -> - {wait_rows1, 0, [[]], ViewSt}; -wait_rows1(start_object, {_, _, Terms, ViewSt}) -> - {collect_object, 0, [[]|Terms], ViewSt}; -wait_rows1(end_array, {_, _, _, ViewSt}) -> - {wait_rows, 0, [[]], ViewSt}. - - -collect_object(start_object, {_, NestCount, Terms, ViewSt}) -> - {collect_object, NestCount + 1, [[]|Terms], ViewSt}; - -collect_object(end_object, {_, NestCount, [[], {key, Key}, Last|Terms], - ViewSt}) -> - {collect_object, NestCount - 1, [[{Key, {[{}]}}] ++ Last] ++ Terms, - ViewSt}; - -collect_object(end_object, {_, NestCount, [Object, {key, Key}, - Last|Terms], ViewSt}) -> - {collect_object, NestCount - 1, - [[{Key, {lists:reverse(Object)}}] ++ Last] ++ Terms, ViewSt}; - -collect_object(end_object, {_, 0, [[], Last|Terms], ViewSt}) -> - [[Row]] = [[{[{}]}] ++ Last] ++ Terms, - send_row(Row, ViewSt); - -collect_object(end_object, {_, NestCount, [[], Last|Terms], ViewSt}) -> - {collect_object, NestCount - 1, [[{[{}]}] ++ Last] ++ Terms, ViewSt}; - -collect_object(end_object, {_, 0, [Object, Last|Terms], ViewSt}) -> - [[Row]] = [[{lists:reverse(Object)}] ++ Last] ++ Terms, - send_row(Row, ViewSt); - - -collect_object(end_object, {_, NestCount, [Object, Last|Terms], ViewSt}) -> - Acc = [[{lists:reverse(Object)}] ++ Last] ++ Terms, - {collect_object, NestCount - 1, Acc, ViewSt}; - - -collect_object(start_array, {_, NestCount, Terms, ViewSt}) -> - {collect_object, NestCount, [[]|Terms], ViewSt}; -collect_object(end_array, {_, NestCount, [List, {key, Key}, Last|Terms], - ViewSt}) -> - {collect_object, NestCount, - [[{Key, lists:reverse(List)}] ++ Last] ++ Terms, ViewSt}; -collect_object(end_array, {_, NestCount, [List, Last|Terms], ViewSt}) -> - {collect_object, NestCount, [[lists:reverse(List)] ++ Last] ++ Terms, - ViewSt}; - -collect_object({key, Key}, {_, NestCount, Terms, ViewSt}) -> - {collect_object, NestCount, [{key, Key}] ++ Terms, - ViewSt}; - -collect_object({_, Event}, {_, NestCount, [{key, Key}, Last|Terms], ViewSt}) -> - {collect_object, NestCount, [[{Key, Event}] ++ Last] ++ Terms, ViewSt}; -collect_object({_, Event}, {_, NestCount, [Last|Terms], ViewSt}) -> - {collect_object, NestCount, [[Event] ++ Last] ++ Terms, ViewSt}. - -send_row(Row, #viewst{owner=Owner, ref=Ref}=ViewSt) -> - Owner ! {Ref, {row, couchbeam_ejson:post_decode(Row)}}, - maybe_continue_decoding(ViewSt). - -%% eventually wait for the next call from the parent -maybe_continue_decoding(#viewst{parent=Parent, - owner=Owner, - ref=Ref, - mref=MRef, - client_ref=ClientRef, - async=once}=ViewSt) -> - receive - {'DOWN', MRef, _, _, _} -> - %% parent exited there is no need to continue - exit(normal); - {Ref, stream_next} -> - {wait_rows1, 0, [[]], ViewSt}; - {Ref, cancel} -> - hackney:close(ClientRef), - %% unregister the stream - ets:delete(couchbeam_view_streams, Ref), - %% tell the parent we exited - Owner ! {Ref, ok}, - %% and exit - exit(normal); - {system, From, Request} -> - sys:handle_system_msg(Request, From, Parent, ?MODULE, [], - {maybe_continue_decoding, ViewSt}); - Else -> - error_logger:error_msg("Unexpected message: ~w~n", [Else]), - %% unregister the stream - ets:delete(couchbeam_view_streams, Ref), - %% report the error - report_error(Else, Ref, Owner), - exit(Else) - after 5000 -> - erlang:hibernate(?MODULE, maybe_continue_decoding, [ViewSt]) - end; - -maybe_continue_decoding(#viewst{parent=Parent, - owner=Owner, - ref=Ref, - mref=MRef, - client_ref=ClientRef}=ViewSt) -> - receive - {'DOWN', MRef, _, _, _} -> - %% parent exited there is no need to continue - exit(normal); - {Ref, cancel} -> - hackney:close(ClientRef), - Owner ! {Ref, ok}, - exit(normal); - {Ref, pause} -> - erlang:hibernate(?MODULE, maybe_continue_decoding, [ViewSt]); - {Ref, resume} -> - {wait_rows1, 0, [[]], ViewSt}; - {system, From, Request} -> - sys:handle_system_msg(Request, From, Parent, ?MODULE, [], - {maybe_continue_decoding, ViewSt}); - Else -> - error_logger:error_msg("Unexpected message: ~w~n", [Else]), - report_error(Else, Ref, Owner), - exit(Else) - after 0 -> - {wait_rows1, 0, [[]], ViewSt} +handle_done(#state{owner=Owner, ref=StreamRef, client_ref=ClientRef, parser=Parser}) -> + %% stop the request and cleanup + catch hackney:stop_async(ClientRef), + catch hackney:skip_body(ClientRef), + %% decode and send rows + try + {Rows, _} = json_stream_parse:finish(Parser), + lists:foreach(fun(Row) -> Owner ! {StreamRef, {row, Row}} end, Rows), + %% unregister the stream + ets:delete(couchbeam_view_streams, StreamRef), + Owner ! {StreamRef, done} + catch _:Reason -> + ets:delete(couchbeam_view_streams, StreamRef), + report_error(Reason, StreamRef, Owner) end. report_error({error, _What}=Error, Ref, Pid) -> diff --git a/src/json_stream_parse.erl b/src/json_stream_parse.erl new file mode 100644 index 00000000..2b2ff1f5 --- /dev/null +++ b/src/json_stream_parse.erl @@ -0,0 +1,103 @@ +%%% -*- erlang -*- +%% Simple streaming JSON row parser for CouchDB view responses. +%% Parses the response and emits each row (as a map) incrementally. + +-module(json_stream_parse). + +-export([init/0, feed/2, finish/1]). + +-record(st, { + phase = find_rows :: find_rows | in_rows | done, + buf = <<>> :: binary(), + i = 0 :: non_neg_integer(), + in_string = false :: boolean(), + escape = false :: boolean(), + arr_depth = 0 :: non_neg_integer(), + obj_depth = 0 :: non_neg_integer(), + obj_start = -1 :: integer() +}). + +init() -> #st{}. + +%% feed(Data, State) -> {Rows, NewState} +feed(Data, #st{buf=Buf0}=S0) when is_binary(Data) -> + S = S0#st{buf = <>}, + parse(S, []). + +finish(S=#st{phase=done}) -> {[], S}; +finish(S) -> + %% Try parse any remaining complete rows + {Rows, S1} = parse(S, []), + {Rows, S1}. + +parse(S=#st{phase=find_rows, buf=Buf, i=I}, Acc) -> + case find_rows_start(Buf, I) of + not_found -> {lists:reverse(Acc), S#st{i=byte_size(Buf)}}; + {_, ArrIdx} -> + S1 = S#st{phase=in_rows, i=ArrIdx+1, arr_depth=1}, + parse(S1, Acc) + end; +parse(S=#st{phase=in_rows, buf=Buf, i=I, + in_string=Str, escape=Esc, + arr_depth=AD, obj_depth=OD, obj_start=OS}, Acc) when I < byte_size(Buf) -> + <<_:I/binary, C, _/binary>> = Buf, + case Str of + true -> + case {Esc, C} of + {true, _} -> parse(S#st{i=I+1, escape=false}, Acc); + {_, $\\} -> parse(S#st{i=I+1, escape=true}, Acc); + {_, $\"} -> parse(S#st{i=I+1, in_string=false}, Acc); + _ -> parse(S#st{i=I+1}, Acc) + end; + false -> + case C of + $\" -> parse(S#st{i=I+1, in_string=true}, Acc); + ${ when OD =:= 0, OS < 0 -> + parse(S#st{i=I+1, obj_depth=1, obj_start=I}, Acc); + ${ -> parse(S#st{i=I+1, obj_depth=OD+1}, Acc); + $} when OD > 0 -> + case OD-1 of + 0 -> + ObjBin = binary:part(Buf, OS, I-OS+1), + Row = couchbeam_ejson:decode(ObjBin), + S1 = S#st{i=I+1, obj_depth=0, obj_start=-1}, + parse(S1, [Row|Acc]); + N -> parse(S#st{i=I+1, obj_depth=N}, Acc) + end; + $[ -> parse(S#st{i=I+1, arr_depth=AD+1}, Acc); + $] -> + case AD-1 of + 0 -> + %% rows array ended; we can stop + %% Drop consumed buffer to current index + {lists:reverse(Acc), S#st{phase=done, i=I+1}}; + N -> parse(S#st{i=I+1, arr_depth=N}, Acc) + end; + _ -> parse(S#st{i=I+1}, Acc) + end + end; +parse(S=#st{phase=in_rows}, Acc) -> {lists:reverse(Acc), S}; +parse(S, Acc) -> {lists:reverse(Acc), S}. + +%% Find the start of the rows array: look for the token "rows" then the following '[' +find_rows_start(Buf, StartI) -> + case binary:match(Buf, <<"\"rows\"">>, [{scope, {StartI, byte_size(Buf)-StartI}}]) of + nomatch -> not_found; + {Pos, _Len} -> + %% find ':' then '[' after it + case find_next(Buf, Pos+5, $:) of + not_found -> not_found; + ColonI -> + case find_next(Buf, ColonI+1, $[) of + not_found -> not_found; + ArrI -> {Pos, ArrI} + end + end + end. + +find_next(Buf, I, Char) when I < byte_size(Buf) -> + <<_:I/binary, C, _/binary>> = Buf, + if C =:= Char -> I; + true -> find_next(Buf, I+1, Char) + end; +find_next(_Buf, _I, _Char) -> not_found. diff --git a/support/test-docker.sh b/support/test-docker.sh new file mode 100644 index 00000000..aa9db9f6 --- /dev/null +++ b/support/test-docker.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +set -euo pipefail + +cd "$(dirname "$0")/.." + +echo "[docker-test] Building and running eunit in containers..." +docker compose up --build --abort-on-container-exit test +rc=$? +echo "[docker-test] Bringing down stack..." +docker compose down -v +exit $rc + diff --git a/support/wait-for-couch.sh b/support/wait-for-couch.sh new file mode 100755 index 00000000..f11f5aad --- /dev/null +++ b/support/wait-for-couch.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +set -euo pipefail + +URL=${COUCHDB_URL:-http://localhost:5984} +USER=${COUCHDB_ADMIN:-admin} +PASS=${COUCHDB_PASSWORD:-change_me} + +echo "Waiting for CouchDB at $URL ..." +for i in {1..60}; do + if curl -fsS "$URL/" >/dev/null; then + echo "CouchDB up." + break + fi + sleep 1 +done + +# verify auth works (if admin party disabled) +curl -fsS -u "$USER:$PASS" "$URL/_all_dbs" >/dev/null || true + +# ensure system databases exist (idempotent) +curl -fsS -u "$USER:$PASS" -X PUT "$URL/_users" >/dev/null || true +curl -fsS -u "$USER:$PASS" -X PUT "$URL/_replicator" >/dev/null || true +curl -fsS -u "$USER:$PASS" -X PUT "$URL/_global_changes" >/dev/null || true +echo "Ready." From 95520b1165ff25a64cb4f8b85e61b4af7cc3c8dd Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Wed, 3 Sep 2025 14:52:32 +0200 Subject: [PATCH 2/7] Add changes module tests --- Makefile | 6 ++++-- rebar3.crashdump | 2 +- src/couchbeam.erl | 6 +++++- src/couchbeam_changes.erl | 36 ++++++++++++++++++++++++++++++++ src/couchbeam_changes_stream.erl | 23 ++++++++++++++++++++ src/couchbeam_view.erl | 25 ++++++++++++++++++++++ src/json_stream_parse.erl | 34 ++++++++++++++++++++++++++++++ support/test-docker.sh | 6 +++--- support/wait-for-couch.sh | 6 +++--- 9 files changed, 134 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 6bace1b9..43934284 100644 --- a/Makefile +++ b/Makefile @@ -16,11 +16,13 @@ docker-logs: $(COMPOSE) logs -f --tail=200 docker-test: - $(COMPOSE) up --build --abort-on-container-exit test ; \ + # Start CouchDB in the background + $(COMPOSE) up -d --build couchdb ; \ + # Run tests as a one-off container, attach only to test output + $(COMPOSE) run --rm test ; \ status=$$? ; \ $(COMPOSE) down -v ; \ exit $$status docker-shell: $(COMPOSE) run --rm test bash - diff --git a/rebar3.crashdump b/rebar3.crashdump index 797813f3..43d2c70d 100644 --- a/rebar3.crashdump +++ b/rebar3.crashdump @@ -9,7 +9,7 @@ Error: terminating {line,114}]}, {rebar_prv_eunit,do,2, [{file,"/usr/src/rebar3-src/apps/rebar/src/rebar_prv_eunit.erl"}, - {line,71}]}, + {line,74}]}, {rebar_core,do,2, [{file,"/usr/src/rebar3-src/apps/rebar/src/rebar_core.erl"}, {line,155}]}, diff --git a/src/couchbeam.erl b/src/couchbeam.erl index efab1e58..3f917a06 100644 --- a/src/couchbeam.erl +++ b/src/couchbeam.erl @@ -1093,13 +1093,17 @@ wait_for_replication(_Db, DocId, 0) -> io:format("Timeout waiting for document ~p to replicate~n", [DocId]), throw({timeout, waiting_for_replication}); wait_for_replication(Db, DocId, Retries) -> - case couchbeam:open_doc(Db, DocId) of + case catch couchbeam:open_doc(Db, DocId) of {ok, _} -> io:format("Document ~p found in target db~n", [DocId]), ok; {error, not_found} -> io:format("Document ~p not found, retries left: ~p~n", [DocId, Retries-1]), timer:sleep(200), + wait_for_replication(Db, DocId, Retries - 1); + _Other -> + io:format("Transient error waiting for document ~p, retries left: ~p~n", [DocId, Retries-1]), + timer:sleep(300), wait_for_replication(Db, DocId, Retries - 1) end. diff --git a/src/couchbeam_changes.erl b/src/couchbeam_changes.erl index aa40d490..6f63b3ca 100644 --- a/src/couchbeam_changes.erl +++ b/src/couchbeam_changes.erl @@ -209,6 +209,42 @@ with_changes_stream(Ref, Fun) -> end end. +-ifdef(TEST). +-include_lib("eunit/include/eunit.hrl"). + +changes_once_normal_test() -> + {ok, _} = application:ensure_all_started(couchbeam), + Server = couchbeam:server_connection(), + {ok, Db} = couchbeam:create_db(Server, <<"couchbeam_changes_test">>), + Docs = [#{<<"_id">> => <<"c1">>}, #{<<"_id">> => <<"c2">>}], + couchbeam:save_docs(Db, Docs), + couchbeam:ensure_full_commit(Db), + {ok, _Seq, Changes} = follow_once(Db, [normal, {since, 0}]), + Ids = [maps:get(<<"id">>, C) || C <- Changes], + ?assert(lists:member(<<"c1">>, Ids)), + ?assert(lists:member(<<"c2">>, Ids)), + ok. + +changes_follow_longpoll_test() -> + {ok, _} = application:ensure_all_started(couchbeam), + Server = couchbeam:server_connection(), + {ok, Db} = couchbeam:create_db(Server, <<"couchbeam_changes_test2">>), + {ok, Ref} = follow(Db, [longpoll, {since, now}]), + %% trigger a change + {ok, _} = couchbeam:save_doc(Db, #{<<"_id">> => <<"lc1">>}), + %% expect one change back + receive + {Ref, {change, Change}} -> + ?assertMatch(#{}, Change), + %% we can cancel after receiving + couchbeam_changes:cancel_stream(Ref), + ok + after 5000 -> + ?assert(false) + end. + +-endif. + changes_request(#db{server=Server, options=ConnOptions}=Db, Options) -> %% if we are filtering the changes using docids, send a POST request diff --git a/src/couchbeam_changes_stream.erl b/src/couchbeam_changes_stream.erl index f00fb82f..e9252eea 100644 --- a/src/couchbeam_changes_stream.erl +++ b/src/couchbeam_changes_stream.erl @@ -411,3 +411,26 @@ maybe_close(#state{client_ref=Ref}) -> % [ post_decode(Term) || Term <- List]; %post_decode(Term) -> % Term. + +-ifdef(TEST). +-include_lib("eunit/include/eunit.hrl"). + +stream_changes_longpoll_test() -> + {ok, _} = application:ensure_all_started(couchbeam), + Server = couchbeam:server_connection(), + {ok, Db} = couchbeam:create_db(Server, <<"couchbeam_changes_stream_test">>), + %% start longpoll stream + {ok, Ref} = couchbeam_changes:follow(Db, [longpoll, {since, now}]), + %% create a change + {ok, _} = couchbeam:save_doc(Db, #{<<"_id">> => <<"sc1">>}), + %% receive change and validate map structure + receive + {Ref, {change, Change}} -> + ?assertMatch(#{}, Change), + ?assertEqual(<<"sc1">>, maps:get(<<"id">>, Change)), + ok + after 5000 -> + ?assert(false) + end. + +-endif. diff --git a/src/couchbeam_view.erl b/src/couchbeam_view.erl index 9cb845e7..a6bfe338 100644 --- a/src/couchbeam_view.erl +++ b/src/couchbeam_view.erl @@ -675,6 +675,31 @@ basic_test() -> Rst5 = couchbeam_view:fold(AccFun, [], Db, {"couchbeam", "test"}, [{start_key, <<"test">>}, {end_key,<<"test3">>}]), ?assertEqual(3, length(Rst5)). +stream_basic_test() -> + start_couchbeam_tests(), + Server = couchbeam:server_connection(), + {ok, Db} = couchbeam:create_db(Server, "couchbeam_testdb"), + Docs = [ + #{<<"_id">> => <<"s1">>}, + #{<<"_id">> => <<"s2">>}, + #{<<"_id">> => <<"s3">>} + ], + couchbeam:save_docs(Db, Docs), + couchbeam:ensure_full_commit(Db), + + {ok, Ref} = stream(Db, 'all_docs', []), + Collected = collect_stream(Ref, []), + %% there may be design docs; ensure at least our 3 are present + Ids = [maps:get(<<"id">>, Row) || Row <- Collected], + ?assert(lists:all(fun(E) -> lists:member(E, Ids) end, [<<"s1">>,<<"s2">>,<<"s3">>])). + +collect_stream(Ref, Acc) -> + receive + {Ref, {row, Row}} -> collect_stream(Ref, [Row|Acc]); + {Ref, done} -> lists:reverse(Acc) + after 5000 -> Acc + end. + view_notfound_test() -> start_couchbeam_tests(), Server = couchbeam:server_connection(), diff --git a/src/json_stream_parse.erl b/src/json_stream_parse.erl index 2b2ff1f5..665a2d4e 100644 --- a/src/json_stream_parse.erl +++ b/src/json_stream_parse.erl @@ -5,6 +5,10 @@ -module(json_stream_parse). -export([init/0, feed/2, finish/1]). +%% tests +-ifdef(TEST). +-export([parse_rows/1]). +-endif. -record(st, { phase = find_rows :: find_rows | in_rows | done, @@ -101,3 +105,33 @@ find_next(Buf, I, Char) when I < byte_size(Buf) -> true -> find_next(Buf, I+1, Char) end; find_next(_Buf, _I, _Char) -> not_found. + +-ifdef(TEST). +-include_lib("eunit/include/eunit.hrl"). + +parse_rows(Json) -> + P0 = init(), + {R1, P1} = feed(Json, P0), + {R2, _} = finish(P1), + R1 ++ R2. + +basic_chunked_parse_test() -> + %% Simulate a view JSON response split in chunks + Row1 = #{<<"id">> => <<"a">>, <<"key">> => <<"a">>, <<"value">> => 1}, + Row2 = #{<<"id">> => <<"b">>, <<"key">> => <<"b">>, <<"value">> => 2}, + BodyMap = #{<<"total_rows">> => 2, <<"offset">> => 0, <<"rows">> => [Row1, Row2]}, + Bin = couchbeam_ejson:encode(BodyMap), + <> = Bin, + P = init(), + {Rows0, P1} = feed(C1, P), + ?assertEqual([], Rows0), + {Rows1, P2} = feed(C2, P1), + %% depending on split, may or may not have a row; just ensure maps when present + lists:foreach(fun(X) -> ?assert(is_map(X)) end, Rows1), + {Rows2, _} = feed(C3, P2), + AllRows = Rows1 ++ Rows2, + ?assertEqual(2, length(AllRows)), + lists:foreach(fun(X) -> ?assert(is_map(X)) end, AllRows), + ok. + +-endif. diff --git a/support/test-docker.sh b/support/test-docker.sh index aa9db9f6..1276bfe1 100644 --- a/support/test-docker.sh +++ b/support/test-docker.sh @@ -3,10 +3,10 @@ set -euo pipefail cd "$(dirname "$0")/.." -echo "[docker-test] Building and running eunit in containers..." -docker compose up --build --abort-on-container-exit test +echo "[docker-test] Starting CouchDB and running eunit..." +docker compose up -d --build couchdb +docker compose run --rm test rc=$? echo "[docker-test] Bringing down stack..." docker compose down -v exit $rc - diff --git a/support/wait-for-couch.sh b/support/wait-for-couch.sh index f11f5aad..75fe02fd 100755 --- a/support/wait-for-couch.sh +++ b/support/wait-for-couch.sh @@ -18,7 +18,7 @@ done curl -fsS -u "$USER:$PASS" "$URL/_all_dbs" >/dev/null || true # ensure system databases exist (idempotent) -curl -fsS -u "$USER:$PASS" -X PUT "$URL/_users" >/dev/null || true -curl -fsS -u "$USER:$PASS" -X PUT "$URL/_replicator" >/dev/null || true -curl -fsS -u "$USER:$PASS" -X PUT "$URL/_global_changes" >/dev/null || true +curl -fs -u "$USER:$PASS" -X PUT "$URL/_users" >/dev/null 2>/dev/null || true +curl -fs -u "$USER:$PASS" -X PUT "$URL/_replicator" >/dev/null 2>/dev/null || true +curl -fs -u "$USER:$PASS" -X PUT "$URL/_global_changes" >/dev/null 2>/dev/null || true echo "Ready." From c4bee237c145e9f47d9d5f03730589bf485f2623 Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Wed, 3 Sep 2025 14:56:43 +0200 Subject: [PATCH 3/7] ignore crashdump from the repo --- .gitignore | 3 ++- rebar3.crashdump | 21 --------------------- 2 files changed, 2 insertions(+), 22 deletions(-) delete mode 100644 rebar3.crashdump diff --git a/.gitignore b/.gitignore index 43df91cb..dac820d4 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ mime.types .rebar *.plt .idea -*.iml \ No newline at end of file +*.im +*.crashdump diff --git a/rebar3.crashdump b/rebar3.crashdump deleted file mode 100644 index 43d2c70d..00000000 --- a/rebar3.crashdump +++ /dev/null @@ -1,21 +0,0 @@ -Error: terminating -[{application_controller,call,2, - [{file,"application_controller.erl"},{line,515}]}, - {rebar_paths,'-purge_and_load/2-lc$^5/1-5-',1, - [{file,"/usr/src/rebar3-src/apps/rebar/src/rebar_paths.erl"}, - {line,110}]}, - {rebar_paths,purge_and_load,2, - [{file,"/usr/src/rebar3-src/apps/rebar/src/rebar_paths.erl"}, - {line,114}]}, - {rebar_prv_eunit,do,2, - [{file,"/usr/src/rebar3-src/apps/rebar/src/rebar_prv_eunit.erl"}, - {line,74}]}, - {rebar_core,do,2, - [{file,"/usr/src/rebar3-src/apps/rebar/src/rebar_core.erl"}, - {line,155}]}, - {rebar3,run_aux,2, - [{file,"/usr/src/rebar3-src/apps/rebar/src/rebar3.erl"},{line,212}]}, - {rebar3,main,1, - [{file,"/usr/src/rebar3-src/apps/rebar/src/rebar3.erl"},{line,66}]}, - {escript,run,2,[{file,"escript.erl"},{line,906}]}] - From 3d7ebd8d2f90dfc1a29a3d47af457402ae9a8c59 Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Wed, 3 Sep 2025 16:06:26 +0200 Subject: [PATCH 4/7] update doc and bump to 2.0 --- NEWS.md | 12 +++++++++ README.md | 59 +++++++++++++++++++---------------------- doc/README.md | 59 +++++++++++++++++++---------------------- doc/couchbeam_util.md | 17 ++++++------ src/couchbeam.app.src | 2 +- src/couchbeam_ejson.erl | 7 ++--- src/couchbeam_util.erl | 14 +++++----- 7 files changed, 88 insertions(+), 82 deletions(-) diff --git a/NEWS.md b/NEWS.md index 966f8972..561c084f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,18 @@ couchbeam NEWS -------------- +version 2.0.0 / 2025-09-03 +-------------------------- + +- move from propos lists to maps for json +- remove JSX & Jiffy Usage for erlang/0TP 28.0+ json module +- View and changes streaming now use a simpler parser + +** BREAKING CHANGE ** + +- move to maps, you will need to migrate your application to use them. +no backward compatibility is provided + version 1.7.1 / 2025-07-24 --------------------------- diff --git a/README.md b/README.md index 8e645eb9..79aea846 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,7 @@ Couchbeam is a simple erlang library for [Barrel](https://barrel-db.org) or [Apa - Stream changes feeds - reduced memory usage - fetch and send attachments in a streaming fashion -- by default use the JSX module to encode/decode JSON -- support [Jiffy](http://github.com/davisp/jiffy) a JSON encoder/decoder -in C. +- JSON encoding/decoding via Erlang/OTP stdlib `json` with maps #### Useful modules are: @@ -151,10 +149,10 @@ Make a new document: ``` erlang -Doc = {[ -{<<"_id">>, <<"test">>}, -{<<"content">>, <<"some text">>} -]}. +Doc = #{ + <<"_id">> => <<"test">>, + <<"content">> => <<"some text">> +}. ``` And save it to the database: @@ -201,18 +199,21 @@ Options = [include_docs], {ok, AllDocs} = couchbeam_view:all(Db, Options). ``` -Ex of results: +Example result (abridged): ``` erlang -{ok,[{[{<<"id">>,<<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>}, - {<<"key">>,<<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>}, - {<<"value">>, - {[{<<"rev">>,<<"15-15c0b3c4efa74f9a80d28ac040f18bdb">>}]}}, - {<<"doc">>, - {[{<<"_id">>,<<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>}, - {<<"_rev">>,<<"15-15c0b3c4efa74f9a80d28ac040f18"...>>}]}}]}, - ]}. +{ok, [ + #{ + <<"id">> => <<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>, + <<"key">> => <<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>, + <<"value">> => #{<<"rev">> => <<"15-15c0b3c4efa74f9a80d28ac040f18bdb">>}, + <<"doc">> => #{ + <<"_id">> => <<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>, + <<"_rev">> => <<"15-15c0b3c4efa74f9a80d28ac040f18"...>> + } + } +]}. ``` All functions to manipulate these results are in the `couchbeam_view` module. @@ -238,21 +239,18 @@ Design doc are created like any documents: ``` erlang -DesignDoc = {[ - {<<"_id">>, <<"_design/couchbeam">>}, - {<<"language">>,<<"javascript">>}, - {<<"views">>, - {[{<<"test">>, - {[{<<"map">>, - <<"function (doc) {\n if (doc.type == \"test\") {\n emit(doc._id, doc);\n}\n}">> - }]} - },{<<"test2">>, - {[{<<"map">>, - <<"function (doc) {\n if (doc.type == \"test2\") {\n emit(doc._id, null);\n}\n}">> - }]} - }]} +DesignDoc = #{ + <<"_id">> => <<"_design/couchbeam">>, + <<"language">> => <<"javascript">>, + <<"views">> => #{ + <<"test">> => #{ + <<"map">> => <<"function (doc) {\n if (doc.type == \"test\") {\n emit(doc._id, doc);\n}\n}">> + }, + <<"test2">> => #{ + <<"map">> => <<"function (doc) {\n if (doc.type == \"test2\") {\n emit(doc._id, null);\n}\n}">> } - ]}, + } +}, {ok, DesignDoc1} = couchbeam:save_doc(Db, DesignDoc). ``` @@ -421,4 +419,3 @@ issue](http://github.com/benoitc/couchbeam/issues). couchbeam_view_stream couchbeam_view_sup gen_changes - diff --git a/doc/README.md b/doc/README.md index d6d736af..3d800bf6 100644 --- a/doc/README.md +++ b/doc/README.md @@ -17,9 +17,7 @@ Couchbeam is a simple erlang library for [Barrel](https://barrel-db.org) or [Apa - Stream changes feeds - reduced memory usage - fetch and send attachments in a streaming fashion -- by default use the JSX module to encode/decode JSON -- support [Jiffy](http://github.com/davisp/jiffy) a JSON encoder/decoder -in C. +- JSON encoding/decoding via Erlang/OTP stdlib `json` with maps #### Useful modules are: @@ -151,10 +149,10 @@ Make a new document: ``` erlang -Doc = {[ -{<<"_id">>, <<"test">>}, -{<<"content">>, <<"some text">>} -]}. +Doc = #{ + <<"_id">> => <<"test">>, + <<"content">> => <<"some text">> +}. ``` And save it to the database: @@ -201,18 +199,21 @@ Options = [include_docs], {ok, AllDocs} = couchbeam_view:all(Db, Options). ``` -Ex of results: +Example result (abridged): ``` erlang -{ok,[{[{<<"id">>,<<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>}, - {<<"key">>,<<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>}, - {<<"value">>, - {[{<<"rev">>,<<"15-15c0b3c4efa74f9a80d28ac040f18bdb">>}]}}, - {<<"doc">>, - {[{<<"_id">>,<<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>}, - {<<"_rev">>,<<"15-15c0b3c4efa74f9a80d28ac040f18"...>>}]}}]}, - ]}. +{ok, [ + #{ + <<"id">> => <<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>, + <<"key">> => <<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>, + <<"value">> => #{<<"rev">> => <<"15-15c0b3c4efa74f9a80d28ac040f18bdb">>}, + <<"doc">> => #{ + <<"_id">> => <<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>, + <<"_rev">> => <<"15-15c0b3c4efa74f9a80d28ac040f18"...>> + } + } +]}. ``` All functions to manipulate these results are in the `couchbeam_view` module. @@ -238,21 +239,18 @@ Design doc are created like any documents: ``` erlang -DesignDoc = {[ - {<<"_id">>, <<"_design/couchbeam">>}, - {<<"language">>,<<"javascript">>}, - {<<"views">>, - {[{<<"test">>, - {[{<<"map">>, - <<"function (doc) {\n if (doc.type == \"test\") {\n emit(doc._id, doc);\n}\n}">> - }]} - },{<<"test2">>, - {[{<<"map">>, - <<"function (doc) {\n if (doc.type == \"test2\") {\n emit(doc._id, null);\n}\n}">> - }]} - }]} +DesignDoc = #{ + <<"_id">> => <<"_design/couchbeam">>, + <<"language">> => <<"javascript">>, + <<"views">> => #{ + <<"test">> => #{ + <<"map">> => <<"function (doc) {\n if (doc.type == \"test\") {\n emit(doc._id, doc);\n}\n}">> + }, + <<"test2">> => #{ + <<"map">> => <<"function (doc) {\n if (doc.type == \"test2\") {\n emit(doc._id, null);\n}\n}">> } - ]}, + } +}, {ok, DesignDoc1} = couchbeam:save_doc(Db, DesignDoc). ``` @@ -421,4 +419,3 @@ issue](http://github.com/benoitc/couchbeam/issues). couchbeam_view_stream couchbeam_view_sup gen_changes - diff --git a/doc/couchbeam_util.md b/doc/couchbeam_util.md index 6810db46..ddcaaa87 100644 --- a/doc/couchbeam_util.md +++ b/doc/couchbeam_util.md @@ -9,7 +9,7 @@ ## Function Index ## -
binary_env/2
dbname/1
deprecated/3
encode_att_name/1
encode_docid/1
encode_docid1/1
encode_docid_noop/1
encode_query/1Encode needed value of Query proplists in json.
encode_query_value/2Encode value in JSON if needed depending on the key.
force_param/3replace a value in a proplist.
get_app_env/2
get_value/2emulate proplists:get_value/2,3 but use faster lists:keyfind/3.
get_value/3
oauth_header/3
parse_options/1make view options a list.
parse_options/2
propmerge/3merge 2 proplists.
propmerge1/2Update a proplist with values of the second.
proxy_header/3
proxy_token/2
shutdown_sync/1
start_app_deps/1Start depedent applications of App.
to_atom/1
to_binary/1
to_integer/1
to_list/1
+
binary_env/2
dbname/1
deprecated/3
encode_att_name/1
encode_docid/1
encode_docid1/1
encode_docid_noop/1
encode_query/1Encode needed query parameter values for JSON.
encode_query_value/2Encode value in JSON if needed depending on the key.
force_param/3Replace a value in a property list.
get_app_env/2
get_value/2Emulate proplists:get_value/2,3 for property lists using lists:keyfind/3.
get_value/3
oauth_header/3
parse_options/1make view options a list.
parse_options/2
propmerge/3Merge two property lists.
propmerge1/2Update a property list with values of the second.
proxy_header/3
proxy_token/2
shutdown_sync/1
start_app_deps/1Start depedent applications of App.
to_atom/1
to_binary/1
to_integer/1
to_list/1
@@ -64,7 +64,7 @@ `encode_query(QSL) -> any()` -Encode needed value of Query proplists in json +Encode needed query parameter values for JSON @@ -80,7 +80,7 @@ Encode value in JSON if needed depending on the key `force_param(Key, Value, Options) -> any()` -replace a value in a proplist +Replace a value in a property list @@ -97,7 +97,7 @@ get_value(Key::term(), Prop::[term()]) -> term()
-emulate proplists:get_value/2,3 but use faster lists:keyfind/3 +Emulate proplists:get_value/2,3 for property lists using faster lists:keyfind/3 @@ -134,8 +134,8 @@ make view options a list `propmerge(F, L1, L2) -> any()` -merge 2 proplists. All the Key - Value pairs from both proplists -are included in the new proplists. If a key occurs in both dictionaries +Merge two property lists (lists of {Key,Value}). All the Key - Value pairs from both lists +are included in the new list. If a key occurs in both dictionaries then Fun is called with the key and both values to return a new value. This a wreapper around dict:merge @@ -145,8 +145,8 @@ value. This a wreapper around dict:merge `propmerge1(L1, L2) -> any()` -Update a proplist with values of the second. In case the same -key is in 2 proplists, the value from the first are kept. +Update a property list with values of the second. In case the same +key is in both lists, the value from the first is kept. @@ -200,4 +200,3 @@ Start depedent applications of App. ### to_list/1 ### `to_list(V) -> any()` - diff --git a/src/couchbeam.app.src b/src/couchbeam.app.src index db0e822f..48fd8df7 100644 --- a/src/couchbeam.app.src +++ b/src/couchbeam.app.src @@ -6,7 +6,7 @@ {application, couchbeam, [{description, "Erlang CouchDB client"}, - {vsn, "1.7.1"}, + {vsn, "2.0.0"}, {modules, []}, {registered, [ couchbeam_sup diff --git a/src/couchbeam_ejson.erl b/src/couchbeam_ejson.erl index 75193418..d1ca4ea9 100644 --- a/src/couchbeam_ejson.erl +++ b/src/couchbeam_ejson.erl @@ -12,8 +12,8 @@ -include("couchbeam.hrl"). -%% Migrate to Erlang/OTP 28 stdlib json module using maps. -%% Objects are represented as maps; arrays as lists. +%% JSON handling uses Erlang/OTP stdlib json with maps. +%% JSON objects are represented as maps; arrays as lists. -spec encode(ejson()) -> binary(). @@ -36,6 +36,7 @@ decode(D) when is_binary(D) -> end; decode(D) -> decode(iolist_to_binary(D)). -%% post_decode was used to convert jsx proplists to ejson; now it is identity. +%% post_decode was previously used to convert jsx proplists / {[...]} objects +%% to ejson. Since objects are now maps, it is identity. post_decode(Term) -> Term. diff --git a/src/couchbeam_util.erl b/src/couchbeam_util.erl index 8ef07e54..7b966574 100644 --- a/src/couchbeam_util.erl +++ b/src/couchbeam_util.erl @@ -62,7 +62,7 @@ encode_docid1(DocId) -> encode_docid_noop(DocId) -> DocId. -%% @doc Encode needed value of Query proplists in json +%% @doc Encode needed query parameter values for JSON encode_query([]) -> []; encode_query(QSL) when is_list(QSL) -> @@ -118,19 +118,19 @@ oauth_header(Url, Action, OauthProps) -> {<<"Authorization">>, list_to_binary(Realm)}. -%% @doc merge 2 proplists. All the Key - Value pairs from both proplists -%% are included in the new proplists. If a key occurs in both dictionaries +%% @doc Merge two property lists (lists of {Key,Value}). All the Key - Value +%% pairs from both lists are included in the new list. If a key occurs in both dictionaries %% then Fun is called with the key and both values to return a new %% value. This a wreapper around dict:merge propmerge(F, L1, L2) -> dict:to_list(dict:merge(F, dict:from_list(L1), dict:from_list(L2))). -%% @doc Update a proplist with values of the second. In case the same -%% key is in 2 proplists, the value from the first are kept. +%% @doc Update a property list with values of the second. In case the same +%% key is in both lists, the value from the first is kept. propmerge1(L1, L2) -> propmerge(fun(_, V1, _) -> V1 end, L1, L2). -%% @doc replace a value in a proplist +%% @doc Replace a value in a property list force_param(Key, Value, Options) -> case couchbeam_util:get_value(Key, Options) of undefined -> @@ -139,7 +139,7 @@ force_param(Key, Value, Options) -> lists:keystore(Key, 1, Options, {Key, Value}) end. -%% @doc emulate proplists:get_value/2,3 but use faster lists:keyfind/3 +%% @doc Emulate proplists:get_value/2,3 for property lists but use faster lists:keyfind/3 -spec get_value(Key :: term(), Prop :: [term()]) -> term(). get_value(Key, Prop) -> get_value(Key, Prop, undefined). From e688f91b82288a0e44dff672406c4959868d298c Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Thu, 4 Sep 2025 23:19:44 +0200 Subject: [PATCH 5/7] Docs: migrate to ExDoc; remove edown; fix EDoc issues; replace @spec with -spec in modules; update examples to maps; include NOTICE/LICENSE/NEWS in ExDoc; update copyright to 2009-2025 Benoit Chesneau --- LICENSE | 2 +- Makefile | 2 + NEWS.md | 19 +- NOTICE | 6 +- README.md | 28 +- doc/README.md | 421 --- doc/couchbeam.md | 783 ------ doc/couchbeam_app.md | 32 - doc/couchbeam_attachments.md | 61 - doc/couchbeam_changes.md | 206 -- doc/couchbeam_changes_stream.md | 99 - doc/couchbeam_changes_sup.md | 35 - doc/couchbeam_deps.md | 117 - doc/couchbeam_doc.md | 187 -- doc/couchbeam_ejson.md | 48 - doc/couchbeam_httpc.md | 83 - doc/couchbeam_sup.md | 32 - doc/couchbeam_util.md | 202 -- doc/couchbeam_uuids.md | 95 - doc/couchbeam_view.md | 402 --- doc/couchbeam_view_stream.md | 99 - doc/couchbeam_view_sup.md | 35 - doc/gen_changes.md | 110 - doc/overview.edoc | 390 --- include/couchbeam.hrl | 4 +- rebar.config | 32 +- site/.build | 34 + site/404.html | 123 + site/api-reference.html | 254 ++ site/couchbeam.epub | Bin 0 -> 77049 bytes site/couchbeam.html | 2386 +++++++++++++++++ site/couchbeam_app.html | 218 ++ site/couchbeam_attachments.html | 402 +++ site/couchbeam_changes.html | 566 ++++ site/couchbeam_changes_stream.html | 374 +++ site/couchbeam_changes_sup.html | 224 ++ site/couchbeam_doc.html | 849 ++++++ site/couchbeam_ejson.html | 499 ++++ site/couchbeam_httpc.html | 568 ++++ site/couchbeam_sup.html | 218 ++ site/couchbeam_util.html | 972 +++++++ site/couchbeam_uuids.html | 544 ++++ site/couchbeam_view.html | 1508 +++++++++++ site/couchbeam_view_stream.html | 344 +++ site/couchbeam_view_sup.html | 224 ++ site/dist/html-DPJLHKSM.js | 222 ++ site/dist/html-erlang-DQDXQC7W.css | 6 + .../dist/lato-latin-400-normal-W7754I4D.woff2 | Bin 0 -> 23580 bytes .../dist/lato-latin-700-normal-2XVSBPG4.woff2 | Bin 0 -> 23040 bytes .../lato-latin-ext-400-normal-N27NCBWW.woff2 | Bin 0 -> 5472 bytes .../lato-latin-ext-700-normal-Q2L5DVMW.woff2 | Bin 0 -> 5368 bytes site/dist/remixicon-QPNJX265.woff2 | Bin 0 -> 2096 bytes site/dist/search_data-37149571.js | 1 + site/dist/sidebar_items-A03F7C15.js | 1 + site/gen_changes.html | 554 ++++ site/index.html | 10 + site/json_stream_parse.html | 248 ++ site/license.html | 170 ++ site/news.html | 192 ++ site/notice.html | 164 ++ site/readme.html | 294 ++ site/search.html | 121 + src/couchbeam.erl | 67 +- src/couchbeam_attachments.erl | 11 +- src/couchbeam_changes.erl | 2 +- src/couchbeam_changes_stream.erl | 11 +- src/couchbeam_doc.erl | 28 +- src/couchbeam_ejson.erl | 2 +- src/couchbeam_httpc.erl | 4 +- src/couchbeam_util.erl | 4 +- src/couchbeam_uuids.erl | 6 +- src/couchbeam_view.erl | 91 +- src/gen_changes.erl | 1 - 73 files changed, 12414 insertions(+), 3633 deletions(-) delete mode 100644 doc/README.md delete mode 100644 doc/couchbeam.md delete mode 100644 doc/couchbeam_app.md delete mode 100644 doc/couchbeam_attachments.md delete mode 100644 doc/couchbeam_changes.md delete mode 100644 doc/couchbeam_changes_stream.md delete mode 100644 doc/couchbeam_changes_sup.md delete mode 100644 doc/couchbeam_deps.md delete mode 100644 doc/couchbeam_doc.md delete mode 100644 doc/couchbeam_ejson.md delete mode 100644 doc/couchbeam_httpc.md delete mode 100644 doc/couchbeam_sup.md delete mode 100644 doc/couchbeam_util.md delete mode 100644 doc/couchbeam_uuids.md delete mode 100644 doc/couchbeam_view.md delete mode 100644 doc/couchbeam_view_stream.md delete mode 100644 doc/couchbeam_view_sup.md delete mode 100644 doc/gen_changes.md delete mode 100644 doc/overview.edoc create mode 100644 site/.build create mode 100644 site/404.html create mode 100644 site/api-reference.html create mode 100644 site/couchbeam.epub create mode 100644 site/couchbeam.html create mode 100644 site/couchbeam_app.html create mode 100644 site/couchbeam_attachments.html create mode 100644 site/couchbeam_changes.html create mode 100644 site/couchbeam_changes_stream.html create mode 100644 site/couchbeam_changes_sup.html create mode 100644 site/couchbeam_doc.html create mode 100644 site/couchbeam_ejson.html create mode 100644 site/couchbeam_httpc.html create mode 100644 site/couchbeam_sup.html create mode 100644 site/couchbeam_util.html create mode 100644 site/couchbeam_uuids.html create mode 100644 site/couchbeam_view.html create mode 100644 site/couchbeam_view_stream.html create mode 100644 site/couchbeam_view_sup.html create mode 100644 site/dist/html-DPJLHKSM.js create mode 100644 site/dist/html-erlang-DQDXQC7W.css create mode 100644 site/dist/lato-latin-400-normal-W7754I4D.woff2 create mode 100644 site/dist/lato-latin-700-normal-2XVSBPG4.woff2 create mode 100644 site/dist/lato-latin-ext-400-normal-N27NCBWW.woff2 create mode 100644 site/dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 create mode 100644 site/dist/remixicon-QPNJX265.woff2 create mode 100644 site/dist/search_data-37149571.js create mode 100644 site/dist/sidebar_items-A03F7C15.js create mode 100644 site/gen_changes.html create mode 100644 site/index.html create mode 100644 site/json_stream_parse.html create mode 100644 site/license.html create mode 100644 site/news.html create mode 100644 site/notice.html create mode 100644 site/readme.html create mode 100644 site/search.html diff --git a/LICENSE b/LICENSE index 6f673fbd..7c2788cf 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -2009-2016 (c) Benoît Chesneau +2009-2025 (c) Benoit Chesneau Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation diff --git a/Makefile b/Makefile index 43934284..3dafe413 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,8 @@ DOCKER?=docker COMPOSE?=docker compose .PHONY: docker-build docker-up docker-down docker-logs docker-test docker-shell +docs: + rebar3 ex_doc docker-build: $(COMPOSE) build diff --git a/NEWS.md b/NEWS.md index 561c084f..00a30467 100644 --- a/NEWS.md +++ b/NEWS.md @@ -164,7 +164,7 @@ version 1.1.1 / 2014-11-11 - update to [hackney 0.15.0](https://github.com/benoitc/hackney/releases ), improving performances and concurrency - fix `couchbeam:doc_exists/2`(#116) -- fix `couchbeam:reply_att/1 (#114) +- fix `couchbeam:reply_att/1` (#114) version 1.1.0 / 2014-10-28 @@ -251,10 +251,9 @@ version 0.10.0 / 2013-12-21 revisions - add support of the [multipart API](http://docs.couchdb.org/en/latest/api/document/common.html#efficient-multiple-attachments-retrieving) when fetching a doc: This change make - `couchbeam:open_doc/3` return a multipart response `{ok, {multipart, -Stream}}` when using the setting `attachments=true` option. A new option -{`accept. <<"multipart/mixed">>}" can also be used with the options -`open_revs` or `revs` to fetch the response as a multipart. + `couchbeam:open_doc/3` returns a multipart response `{ok, {multipart, Stream}}` + when using the `attachments=true` option. A new option `{accept, <<"multipart/mixed">>}` + can also be used with the options `open_revs` or `revs` to fetch the response as a multipart. - bump the [hackney](http://github.com/benoitc/hackney) version to **0.9.1** . @@ -266,7 +265,7 @@ attachments or a doc wit all its revisions. version 0.9.3 / 2013-12-07 -------------------------- -- fix: `couchbeam:open_or_create_db/2' +- fix: couchbeam:open_or_create_db/2 version 0.9.2 / 2013-12-07 -------------------------- @@ -284,17 +283,17 @@ version 0.9.0 / 2013-12-05 This is a major release pre-1.0. API is now frozen and won't change much until the version 1.0. -- replaced the use of `ibrowse` by `hackney` to handle HTTP connections +- replaced the use of ibrowse by hackney to handle HTTP connections - new [streaming API](https://github.com/benoitc/couchbeam#stream-view-results) in view - breaking change: remobe - breaking change: remove deprecated view API. Everything is now managed in the [couch_view](https://github.com/benoitc/couchbeam/blob/master/doc/couchbeam_view.md) module. -- replace `couchbeam_changes:stream` and `couchbeam_changes:fetch` - functions by `couchbeam_changes/follow` and `couchbeam_changes:follow_once`. +- replace 'couchbeam_changes:stream' and 'couchbeam_changes:fetch' + functions by 'couchbeam_changes/follow' and 'couchbeam_changes:follow_once'. - breaking change: new attachment API - new: JSX a pure erlang JSON encoder/decoder is now the default. Jiffy - can be set at the compilation by defining `WITH_JIFFY` in the Erlang + can be set at the compilation by defining 'WITH_JIFFY' in the Erlang options. - removed mochiweb dependency. diff --git a/NOTICE b/NOTICE index 5dcd4531..a56b2087 100644 --- a/NOTICE +++ b/NOTICE @@ -1,7 +1,7 @@ -Couchdbeam ----------- +Couchbeam +--------- -2009-2016 (c) Benoitît Chesneau +2009-2025 (c) Benoit Chesneau couchbeam is released under the MIT license. See the LICENSE file for the complete license. diff --git a/README.md b/README.md index 79aea846..c3c5faef 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # Couchbeam - simple Apache CouchDB client library for Erlang applications # -Copyright (c) 2009-2025 Benoît Chesneau. +Copyright (c) 2009-2025 Benoit Chesneau. __Version:__ 1.7.1 @@ -318,7 +318,7 @@ To fetch an attachment: {ok Att1} = couchbeam:fetch_attachment(Db, DocId, AttName). ``` -You can use `couchbeam:stream_fetch_attachment/6` for the stream +You can use `couchbeam:stream_attachment/1` for the stream fetch. To delete an attachment: @@ -376,7 +376,7 @@ for more info. You can authenticate to the database or Apache CouchDB or RCOUCH server by filling options to the Option list in `couchbeam:server_connection/4` for the server or in `couchbeam:create_db/3`, `couchbeam:open_db/3`, -`couchbeam:wopen_or_create_db/3` functions. +`couchbeam:open_or_create_db/3` functions. To set basic_auth on a server: @@ -397,25 +397,3 @@ in the `couchbeam:server_connection/2` documentation. For issues, comments or feedback please [create an issue](http://github.com/benoitc/couchbeam/issues). - - -## Modules ## - - - - - - - - - - - - - - - - - - -
couchbeam
couchbeam_app
couchbeam_attachments
couchbeam_changes
couchbeam_changes_stream
couchbeam_changes_sup
couchbeam_doc
couchbeam_ejson
couchbeam_httpc
couchbeam_sup
couchbeam_util
couchbeam_uuids
couchbeam_view
couchbeam_view_stream
couchbeam_view_sup
gen_changes
diff --git a/doc/README.md b/doc/README.md deleted file mode 100644 index 3d800bf6..00000000 --- a/doc/README.md +++ /dev/null @@ -1,421 +0,0 @@ - - -# Couchbeam - simple Apache CouchDB client library for Erlang applications # - -Copyright (c) 2009-2025 Benoît Chesneau. - -__Version:__ 1.5.0 - -# couchbeam - -Couchbeam is a simple erlang library for [Barrel](https://barrel-db.org) or [Apache CouchDB](http://couchdb.apache.org). Couchbeam provides you a full featured and easy client to access and manage multiple nodes. - -#### Main features: - -- Complete support of the BarrelDB and Apache CouchDB API -- Stream view results to your app -- Stream changes feeds -- reduced memory usage -- fetch and send attachments in a streaming fashion -- JSON encoding/decoding via Erlang/OTP stdlib `json` with maps - -#### Useful modules are: - -- [`couchbeam`](couchbeam.md): The `couchbeam` module is the main interface for interaction with this application. It includes functions for managing connections to Apache CouchDB or RCOUCH servers and databases and for performing document creations, updates, deletes, views... -- [`couchbeam_doc`](couchbeam_doc.md) Module to manipulate Documents structures. You can set values, -updates keys, ... -- [`couchbeam_attachments`](couchbeam_attachments.md): Module to manipulate attachments. You can add, remove -attachments in a Document structure (inline attachments). -- [`couchbeam_view`](couchbeam_view.md): Module to manage view results. -- [`couchbeam_changes`](couchbeam_changes.md): Module to manage changes feeds. Follow continuously -the changes in a db or get all changes at once. - -The goal of Couchbeam is to ease the access to the Apache CouchDB and RCOUCH HTTP API in erlang. - -Read the [NEWS](https://raw.github.com/benoitc/couchbeam/master/NEWS) file -to get last changelog. - -## Installation - -Download the sources from our [Github repository](http://github.com/benoitc/couchbeam) - -To build the application simply run 'make'. This should build .beam, .app -files and documentation. - -To run tests run 'make test'. -To generate doc, run 'make doc'. - -Or add it to your rebar config - -``` - erlang -{deps, [ - .... - {couchbeam, ".*", {git, "git://github.com/benoitc/couchbeam.git", {branch, "master"}}} -]}. -``` - -Note to compile with jiffy you need to define in the erlang options the -variable `WITH_JIFFY`. - -if you use rebar, add to your `rebar.config`: - -``` - erlang -{erl_opts, [{d, 'WITH_JIFFY'}]}. -``` - -or use the `rebar` command with the `-D` options: - -``` - sh -rebar compile -DWITH_JIFFY -``` - -## Basic Usage - -### Start couchbeam - -Couchbeam is an [OTP](http://www.erlang.org/doc/design_principles/users_guide.html) -application. You have to start it first before using any of the -functions. The couchbeam application will start the default socket pool -for you. - -To start in the console run: - -``` - sh -$ erl -pa ebin -1> couchbeam:start(). -ok -``` - -It will start hackney and all of the application it depends on: - -``` - erlang -application:start(crypto), -application:start(asn1), -application:start(public_key), -application:start(ssl), -application:start(hackney), -application:start(couchbeam). -``` - -Or add couchbeam to the applications property of your .app in a release - -### Create a connection to the server - -To create a connection to a server machine: - -``` - erlang -Url = "http://localhost:5984", -Options = [], -S = couchbeam:server_connection(Url, Options). -``` - -Test the connection with `couchbeam:server_info/1` : - -``` - erlang -{ok, _Version} = couchbeam:server_info(S). -``` - -### Open or Create a database - -All document operations are done in databases. To open a database simply do: - -``` - erlang -Options = [], -{ok, Db} = couchbeam:open_db(Server, "testdb", Options). -``` - -To create a new one: - -``` - erlang -Options = [], -{ok, Db} = couchbeam:create_db(Server, "testdb", Options). -``` - -You can also use the shorcut `couchbeam:open_or_create_db/3`. that -will create a database if it does not exist. - -### Make a new document - -Make a new document: - -``` - erlang -Doc = #{ - <<"_id">> => <<"test">>, - <<"content">> => <<"some text">> -}. -``` - -And save it to the database: - -``` - erlang -{ok, Doc1} = couchbeam:save_doc(Db, Doc). -``` - -The `couchbeam:save_doc/2` return a new document with updated -revision and if you do not specify the _id, a unique document id. - -To change an document property use functions from `couchbeam_doc`. - -### Retrieve a document - -To retrieve a document do: - -``` - erlang -{ok, Doc2} = couchbeam:open_doc(Db, "test"). -``` - -If you want a specific revision: - -``` - erlang -Rev = couchbeam_doc:get_rev(Doc1), -Options = [{rev, Rev}], -{ok, Doc3} = couchbeam:open_doc(Db, "test", Options). -``` - -Here we get the revision from the document we previously stored. Any -options from the Apache CouchDB and RCOUCH API can be used. - -### Get all documents - -To get all documents you have first to create an object -that will keep all informations. - -``` - erlang -Options = [include_docs], -{ok, AllDocs} = couchbeam_view:all(Db, Options). -``` - -Example result (abridged): - -``` - erlang -{ok, [ - #{ - <<"id">> => <<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>, - <<"key">> => <<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>, - <<"value">> => #{<<"rev">> => <<"15-15c0b3c4efa74f9a80d28ac040f18bdb">>}, - <<"doc">> => #{ - <<"_id">> => <<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>, - <<"_rev">> => <<"15-15c0b3c4efa74f9a80d28ac040f18"...>> - } - } -]}. -``` - -All functions to manipulate these results are in the `couchbeam_view` module. - -### Couch DB views - -Views are workin like all_docs. You have to create a View object before -doing anything. - -``` - erlang -Options = [], -DesignName = "designname", -ViewName = "viewname", -{ok, ViewResults} = couchbeam_view:fetch(Db, {DesignName, ViewName}, Options). -``` - -Like the `all_docs` function, use the functions -from `couchbeam_view` module to manipulate results. You can pass -any querying options from the [view API](http://docs.rcouch.org/en/latest/api/ddoc/views.html). - -Design doc are created like any documents: - -``` - erlang -DesignDoc = #{ - <<"_id">> => <<"_design/couchbeam">>, - <<"language">> => <<"javascript">>, - <<"views">> => #{ - <<"test">> => #{ - <<"map">> => <<"function (doc) {\n if (doc.type == \"test\") {\n emit(doc._id, doc);\n}\n}">> - }, - <<"test2">> => #{ - <<"map">> => <<"function (doc) {\n if (doc.type == \"test2\") {\n emit(doc._id, null);\n}\n}">> - } - } -}, -{ok, DesignDoc1} = couchbeam:save_doc(Db, DesignDoc). -``` - -You can also use [couchapp](http://github.com/couchapp/couchapp) to manage them -more easily. - -### Stream View results - -While you can get results using `couchbeam_views:fetch/2`, you can also retrieve -all rows in a streaming fashion: - -``` - erlang -ViewFun = fun(Ref, F) -> - receive - {Ref, done} -> - io:format("done", []), - done; - {Ref, {row, Row}} -> - io:format("got ~p~n", [Row]), - F(Ref, F); - {error, Ref, Error} -> - io:format("error: ~p~n", [Error]) - end -end, - -{ok, StreamRef} = couchbeam_view:stream(Db, 'all_docs'), -ViewFun(StreamRef, ViewFun), -{ok, StreamRef2} = couchbeam_view:stream(Db, 'all_docs', [include_docs]), -ViewFun(StreamRef2, ViewFun). -``` - -You can of course do the same with a view: - -``` - erlang -DesignNam = "designname", -ViewName = "viewname", -{ok, StreamRef3} = couchbeam_view:stream(Db, {DesignNam, ViewName}, [include_docs]), -ViewFun(StreamRef3, ViewFun). -``` - -### Put, Fetch and Delete documents attachments - -You can add attachments to any documents. Attachments could be anything. - -To send an attachment: - -``` - erlang -DocID = "test", -AttName = "test.txt", -Att = "some content I want to attach", -Options = [] -{ok, _Result} = couchbeam:put_attachment(Db, DocId, AttName, Att, Options). -``` - -All attachments are streamed to servers. `Att` could be also be an iolist -or functions, see `couchbeam:put_attachment/5` for more information. - -To fetch an attachment: - -``` - erlang -{ok Att1} = couchbeam:fetch_attachment(Db, DocId, AttName). -``` - -You can use `couchbeam:stream_fetch_attachment/6` for the stream -fetch. - -To delete an attachment: - -``` - erlang -{ok, Doc4} = couchbeam:open_doc(Db, DocID), -ok = couchbeam:delete_attachment(Db, Doc4, AttName). -``` - -### Changes - -Apache CouchDB and RCOUCH provide a means to get a list of changes made to documents in -the database. With couchbeam you can get changes using `couchbeam_changes:follow_once/2`. -This function returns all changes immediately. But you can also retrieve -all changes rows using longpolling : - -``` - erlang -Options = [], -{ok, LastSeq, Rows} = couchbeam_changes:follow_once(Db, Options). -``` - -Options can be any Changes query parameters. See the [change API](http://docs.rcouch.org/en/latest/api/database/changes.html) for more informations. - -You can also get [continuous](http://docs.rcouch.org/en/latest/api/database/changes.html#continuous): - -``` - erlang -ChangesFun = fun(StreamRef, F) -> - receive - {StreamRef, {done, LastSeq}} -> - io:format("stopped, last seq is ~p~n", [LastSeq]), - ok; - {StreamRef, {change, Change}} -> - io:format("change row ~p ~n", [Change]), - F(StreamRef, F); - {StreamRef, Error}-> - io:format("error ? ~p ~n,", [Error]) - end -end, -Options = [continuous, heartbeat], -{ok, StreamRef} = couchbeam_changes:follow(Db, Options), -ChangesFun(StreamRef, ChangesFun). -``` - -> **Note**: a `gen_changes` behaviour exists in couchbeam that you can -use to create your own specific gen_server receiving changes. Have a -look in the -[example](https://github.com/benoitc/couchbeam/blob/master/examples/test_gen_changes.erl) -for more info. - -### Authentication/ Connections options - -You can authenticate to the database or Apache CouchDB or RCOUCH server by filling -options to the Option list in `couchbeam:server_connection/4` for the -server or in `couchbeam:create_db/3`, `couchbeam:open_db/3`, -`couchbeam:wopen_or_create_db/3` functions. - -To set basic_auth on a server: - -``` - erlang -UserName = "guest", -Password = "test", -Url = "http://localhost:5984", -Options = [{basic_auth, {UserName, Password}}], -S1 = couchbeam:server_connection(Url, Options). -``` - -Couchbeam support SSL, OAuth, Basic Authentication, and Proxy. You can -also set a cookie. For more informations about the options have a look -in the `couchbeam:server_connection/2` documentation. - -## Contribute - -For issues, comments or feedback please [create an -issue](http://github.com/benoitc/couchbeam/issues). - - -## Modules ## - - - - - - - - - - - - - - - - - - -
couchbeam
couchbeam_app
couchbeam_attachments
couchbeam_changes
couchbeam_changes_stream
couchbeam_changes_sup
couchbeam_doc
couchbeam_ejson
couchbeam_httpc
couchbeam_sup
couchbeam_util
couchbeam_uuids
couchbeam_view
couchbeam_view_stream
couchbeam_view_sup
gen_changes
diff --git a/doc/couchbeam.md b/doc/couchbeam.md deleted file mode 100644 index 964a35bc..00000000 --- a/doc/couchbeam.md +++ /dev/null @@ -1,783 +0,0 @@ - - -# Module couchbeam # -* [Data Types](#types) -* [Function Index](#index) -* [Function Details](#functions) - - - -## Data Types ## - - - - -### doc_stream() ### - - -__abstract datatype__: `doc_stream()` - - - - -### mp_attachments() ### - - -

-mp_attachments() = {Name::binary(), Bin::binary()} | {Name::binary(), Bin::binary(), Encoding::binary()} | {Name::binary(), Bin::binary(), Type::binary(), Encoding::binary()} | {Name::binary(), {file, Path::string()}} | {Name::binary(), {file, Path::string()}, Encoding::binary()} | {Name::binary(), Fun::function(), Length::integer()} | {Name::binary(), Fun::function(), Length::integer(), Encoding::binary()} | {Name::binary(), Fun::function(), Length::integer(), Type::binary(), Encoding::binary()} | {Name::binary(), {Fun::function(), Acc::any()}, Length::integer()} | {Name::binary(), {Fun::function(), Acc::any()}, Length::integer(), Encoding::binary()} | {Name::binary(), {Fun::function(), Acc::any()}, Length::integer(), Type::binary(), Encoding::binary()}
-
- - - -## Function Index ## - - -
all_dbs/1get list of databases on a CouchDB node.
all_dbs/2get list of databases on a CouchDB node with optional filter.
compact/1Compaction compresses the database file by removing unused -sections created during updates.
compact/2Like compact/1 but this compacts the view index from the -current version of the design document.
copy_doc/2duplicate a document using the doc API.
copy_doc/3copy a doc to a destination.
create_db/2Create a database and a client for connectiong to it.
create_db/3Create a database and a client for connectiong to it.
create_db/4Create a database and a client for connectiong to it.
db_exists/2test if db with dbname exists on the CouchDB node.
db_info/1get database info.
delete_attachment/3delete a document attachment.
delete_attachment/4delete a document attachment.
delete_db/1delete database.
delete_db/2delete database.
delete_doc/2delete a document.
delete_doc/3delete a document -if you want to make sure the doc it emptied on delete, use the option -{empty_on_delete, true} or pass a doc with just _id and _rev -members.
delete_docs/2delete a list of documents.
delete_docs/3delete a list of documents -if you want to make sure the doc it emptied on delete, use the option -{empty_on_delete, true} or pass a doc with just _id and _rev -members.
design_info/2
doc_exists/2test if doc with uuid exists in the given db.
end_doc_stream/1stop to receive the multipart response of the doc api and close -the connection.
ensure_full_commit/1commit all docs in memory.
ensure_full_commit/2commit all docs in memory.
fetch_attachment/3fetch a document attachment.
fetch_attachment/4fetch a document attachment -Options are -
    -
  • stream: to start streaming an attachment. the function return -{ok, Ref} where is a ref to the attachment
  • -
  • Other options that can be sent using the REST API
  • -
.
get_missing_revs/2get missing revisions.
get_uuid/1Get one uuid from the server.
get_uuids/2Get a list of uuids from the server.
lookup_doc_rev/2get the last revision of the document.
lookup_doc_rev/3
open_db/2Create a client for connection to a database.
open_db/3Create a client for connection to a database.
open_doc/2open a document.
open_doc/3open a document -Params is a list of query argument.
open_or_create_db/2Create a client for connecting to a database and create the -database if needed.
open_or_create_db/3Create a client for connecting to a database and create the -database if needed.
open_or_create_db/4Create a client for connecting to a database and create the -database if needed.
put_attachment/4put an attachment.
put_attachment/5put an attachment.
replicate/2Handle replication.
replicate/3Handle replication.
replicate/4handle Replication.
save_doc/2save a document.
save_doc/3save a *document -A document is a Json object like this one:.
save_doc/4save a *document with all its attacjments -A document is a Json object like this one:.
save_docs/2save a list of documents.
save_docs/3save a list of documents.
send_attachment/2send an attachment chunk -Msg could be Data, eof to stop sending.
server_connection/0Create a server for connectiong to a CouchDB node.
server_connection/1
server_connection/2Create a server for connectiong to a CouchDB node.
server_connection/4Create a server for connectiong to a CouchDB node.
server_info/1Get Information from the server.
stream_attachment/1fetch an attachment chunk.
stream_doc/1stream the multipart response of the doc API.
view_cleanup/1
- - - - -## Function Details ## - - - -### all_dbs/1 ### - -

-all_dbs(Server::server()) -> {ok, iolist()}
-
-
- -get list of databases on a CouchDB node - - - -### all_dbs/2 ### - -

-all_dbs(Server::server(), Options::view_options()) -> {ok, iolist()}
-
-
- -get list of databases on a CouchDB node with optional filter - - - -### compact/1 ### - -

-compact(Db::db()) -> ok | {error, term()}
-
-
- -Compaction compresses the database file by removing unused -sections created during updates. -See [`http://wiki.apache.org/couchdb/Compaction`](http://wiki.apache.org/couchdb/Compaction) for more informations - - - -### compact/2 ### - -

-compact(Db::db(), ViewName::string()) -> ok | {error, term()}
-
-
- -Like compact/1 but this compacts the view index from the -current version of the design document. -See [`http://wiki.apache.org/couchdb/Compaction#View_compaction`](http://wiki.apache.org/couchdb/Compaction#View_compaction) for more informations - - - -### copy_doc/2 ### - -`copy_doc(Db, Doc) -> any()` - -duplicate a document using the doc API - - - -### copy_doc/3 ### - -`copy_doc(Db, Doc, Dest) -> any()` - -copy a doc to a destination. If the destination exist it will -use the last revision, in other case a new doc is created with the -the current doc revision. - - - -### create_db/2 ### - -`create_db(Server, DbName) -> any()` - -Equivalent to [`create_db(Server, DbName, [], [])`](#create_db-4). - -Create a database and a client for connectiong to it. - - - -### create_db/3 ### - -`create_db(Server, DbName, Options) -> any()` - -Equivalent to [`create_db(Server, DbName, Options, [])`](#create_db-4). - -Create a database and a client for connectiong to it. - - - -### create_db/4 ### - -

-create_db(Server::server(), DbName::string(), Options::optionList(), Params::list()) -> {ok, db() | {error, Error}}
-
-
- -Create a database and a client for connectiong to it. - -Connections are made to: - -``` - http://Host:PortPrefix/DbName -``` - -If ssl is set https is used. See server_connections for options. -Params is a list of optionnal query argument you want to pass to the -db. Useful for bigcouch for example. - - - -### db_exists/2 ### - -

-db_exists(Server::server(), DbName::string()) -> boolean()
-
-
- -test if db with dbname exists on the CouchDB node - - - -### db_info/1 ### - -

-db_info(Db::db()) -> {ok, iolist() | {error, Error}}
-
-
- -get database info - - - -### delete_attachment/3 ### - -`delete_attachment(Db, Doc, Name) -> any()` - -Equivalent to [`delete_attachment(Db, Doc, Name, [])`](#delete_attachment-4). - -delete a document attachment - - - -### delete_attachment/4 ### - -`delete_attachment(Db, DocOrDocId, Name, Options) -> any()` - -delete a document attachment - - - -### delete_db/1 ### - -`delete_db(Db) -> any()` - -Equivalent to [`delete_db(Server, DbName)`](#delete_db-2). - -delete database - - - -### delete_db/2 ### - -

-delete_db(Server::server(), DbName) -> {ok, iolist() | {error, Error}}
-
-
- -delete database - - - -### delete_doc/2 ### - -`delete_doc(Db, Doc) -> any()` - -Equivalent to [`delete_doc(Db, Doc, [])`](#delete_doc-3). - -delete a document - - - -### delete_doc/3 ### - -

-delete_doc(Db, Doc, Options) -> {ok, Result} | {error, Error}
-
-
- -delete a document -if you want to make sure the doc it emptied on delete, use the option -{empty_on_delete, true} or pass a doc with just _id and _rev -members. - - - -### delete_docs/2 ### - -`delete_docs(Db, Docs) -> any()` - -Equivalent to [`delete_docs(Db, Docs, [])`](#delete_docs-3). - -delete a list of documents - - - -### delete_docs/3 ### - -

-delete_docs(Db::db(), Docs::list(), Options::list()) -> {ok, Result} | {error, Error}
-
-
- -delete a list of documents -if you want to make sure the doc it emptied on delete, use the option -{empty_on_delete, true} or pass a doc with just _id and _rev -members. - - - -### design_info/2 ### - -`design_info(Db, DesignName) -> any()` - - - -### doc_exists/2 ### - -

-doc_exists(Db::db(), DocId::string()) -> boolean()
-
-
- -test if doc with uuid exists in the given db - - - -### end_doc_stream/1 ### - -

-end_doc_stream(X1::doc_stream()) -> ok
-
-
- -stop to receive the multipart response of the doc api and close -the connection. - - - -### ensure_full_commit/1 ### - -`ensure_full_commit(Db) -> any()` - -Equivalent to [`ensure_full_commit(Db, [])`](#ensure_full_commit-2). - -commit all docs in memory - - - -### ensure_full_commit/2 ### - -

-ensure_full_commit(Db::db(), Options::list()) -> {ok, InstancestartTime::binary()} | {error, term()}
-
-
- -commit all docs in memory - - - -### fetch_attachment/3 ### - -`fetch_attachment(Db, DocId, Name) -> any()` - -Equivalent to [`fetch_attachment(Db, DocId, Name, [])`](#fetch_attachment-4). - -fetch a document attachment - - - -### fetch_attachment/4 ### - -

-fetch_attachment(Db::db(), DocId::string(), Name::string(), Options0::list()) -> {ok, binary()} | {ok, atom()} | {error, term()}
-
-
- -fetch a document attachment -Options are - -* `stream`: to start streaming an attachment. the function return -`{ok, Ref}` where is a ref to the attachment - -* Other options that can be sent using the REST API - - - - - -### get_missing_revs/2 ### - -

-get_missing_revs(Db::#db{}, IdRevs::[{binary(), [binary()]}]) -> {ok, [{DocId::binary(), [MissingRev::binary()], [PossibleAncestor::binary()]}]} | {error, term()}
-
-
- -get missing revisions - - - -### get_uuid/1 ### - -

-get_uuid(Server::server()) -> lists()
-
-
- -Get one uuid from the server - - - -### get_uuids/2 ### - -

-get_uuids(Server::server(), Count::integer()) -> lists()
-
-
- -Get a list of uuids from the server - - - -### lookup_doc_rev/2 ### - -`lookup_doc_rev(Db, DocId) -> any()` - -get the last revision of the document - - - -### lookup_doc_rev/3 ### - -`lookup_doc_rev(Db, DocId, Params) -> any()` - - - -### open_db/2 ### - -`open_db(Server, DbName) -> any()` - -Equivalent to [`open_db(Server, DbName, [])`](#open_db-3). - -Create a client for connection to a database - - - -### open_db/3 ### - -

-open_db(Server::server(), DbName::string(), Options::optionList()) -> {ok, db()}
-
-
- -Create a client for connection to a database - - - -### open_doc/2 ### - -`open_doc(Db, DocId) -> any()` - -Equivalent to [`open_doc(Db, DocId, [])`](#open_doc-3). - -open a document - - - -### open_doc/3 ### - -

-open_doc(Db::db(), DocId::string(), Params::list()) -> {ok, Doc} | {error, Error}
-
-
- -open a document -Params is a list of query argument. Have a look in CouchDb API - - - -### open_or_create_db/2 ### - -`open_or_create_db(Server, DbName) -> any()` - -Equivalent to [`open_or_create_db(Server, DbName, [], [])`](#open_or_create_db-4). - -Create a client for connecting to a database and create the -database if needed. - - - -### open_or_create_db/3 ### - -`open_or_create_db(Server, DbName, Options) -> any()` - -Equivalent to [`open_or_create_db(Server, DbName, Options, [])`](#open_or_create_db-4). - -Create a client for connecting to a database and create the -database if needed. - - - -### open_or_create_db/4 ### - -

-open_or_create_db(Server::server(), DbName0::string(), Options::list(), Params::list()) -> {ok, db() | {error, Error}}
-
-
- -Create a client for connecting to a database and create the -database if needed. - - - -### put_attachment/4 ### - -`put_attachment(Db, DocId, Name, Body) -> any()` - -Equivalent to [`put_attachment(Db, DocId, Name, Body, [])`](#put_attachment-5). - -put an attachment - - - -### put_attachment/5 ### - -

-put_attachment(Db::db(), DocId::string(), Name::string(), Body::body(), Option::optionList()) -> {ok, iolist()}
-
- - - -put an attachment - - - -### replicate/2 ### - -

-replicate(Server::server(), RepObj::{list()}) -> {ok, Result} | {error, Error}
-
-
- -Handle replication. Pass an object containting all informations -It allows to pass for example an authentication info - -``` - RepObj = {[ - {<<"source">>, <<"sourcedb">>}, - {<<"target">>, <<"targetdb">>}, - {<<"create_target">>, true} - ]} - replicate(Server, RepObj). -``` - - - - -### replicate/3 ### - -

-replicate(Server::server(), Source::string(), Target::target()) -> {ok, Result} | {error, Error}
-
-
- -Handle replication. - - - -### replicate/4 ### - -`replicate(Server, Source, Target, Options) -> any()` - -handle Replication. Allows to pass options with source and -target. Options is a Json object. -ex: - -``` - Options = [{<<"create_target">>, true}]} - couchbeam:replicate(S, "testdb", "testdb2", Options). -``` - - - -### save_doc/2 ### - -`save_doc(Db, Doc) -> any()` - -Equivalent to [`save_doc(Db, Doc, [])`](#save_doc-3). - -save a document - - - -### save_doc/3 ### - -

-save_doc(Db::db(), Doc, Options::list()) -> {ok, Doc1} | {error, Error}
-
-
- -save a *document -A document is a Json object like this one: - -``` - {[ - {<<"_id">>, <<"myid">>}, - {<<"title">>, <<"test">>} - ]} -``` - -Options are arguments passed to the request. This function return a -new document with last revision and a docid. If _id isn't specified in -document it will be created. Id is created by extracting an uuid from -the couchdb node. - - - -### save_doc/4 ### - -

-save_doc(Db::db(), Doc::doc(), Atts::mp_attachments(), Options::list()) -> {ok, doc()} | {error, term()}
-
-
- -save a *document with all its attacjments -A document is a Json object like this one: - -``` - {[ - {<<"_id">>, <<"myid">>}, - {<<"title">>, <<"test">>} - ]} -``` - -Options are arguments passed to the request. This function return a -new document with last revision and a docid. If _id isn't specified in -document it will be created. Id is created by extracting an uuid from -the couchdb node. - -If the attachments is not empty, the doc will be sent as multipart. -Attachments are passed as a list of the following tuples: - -- `{Name :: binary(), Bin :: binary()}` -- `{Name :: binary(), Bin :: binary(), Encoding :: binary()}` -- `{ Name :: binary(), Bin :: binary(), Type :: binary(), Encoding :: binary()}` -- `{ Name :: binary(), {file, Path :: string()}}` -- `{ Name :: binary(), {file, Path :: string()}, Encoding :: binary()}` -- `{ Name :: binary(), Fun :: fun(), Length :: integer()}` -- `{ Name :: binary(), Fun :: fun(), Length :: integer(), Encoding :: binary()}` -- `{Name :: binary(), Fun :: fun(), Length :: integer(), Type :: binary(), Encoding :: binary()}` -- `{ Name :: binary(), {Fun :: fun(), Acc :: any()}, Length :: integer()}` -- `{ Name :: binary(), {Fun :: fun(), Acc :: any()}, Length :: integer(), Encoding :: binary()}` -- `{ Name :: binary(), {Fun :: fun(), Acc :: any()}, Length :: integer(), Type :: binary(), Encoding :: binary()}.` - -where `Type` is the content-type of the attachments (detected in other -case) and `Encoding` the encoding of the attachments: -`<<"identity">>` if normal or `<<"gzip">>` if the attachments is -gzipped. - - - -### save_docs/2 ### - -`save_docs(Db, Docs) -> any()` - -Equivalent to [`save_docs(Db, Docs, [])`](#save_docs-3). - -save a list of documents - - - -### save_docs/3 ### - -

-save_docs(Db::db(), Docs::list(), Options::list()) -> {ok, Result} | {error, Error}
-
-
- -save a list of documents - - - -### send_attachment/2 ### - -`send_attachment(Ref, Msg) -> any()` - -send an attachment chunk -Msg could be Data, eof to stop sending. - - - -### server_connection/0 ### - -`server_connection() -> any()` - -Equivalent to [`server_connection("127.0.0.1", 5984, "", [], false)`](#server_connection-5). - -Create a server for connectiong to a CouchDB node - - - -### server_connection/1 ### - -`server_connection(URL) -> any()` - - - -### server_connection/2 ### - -`server_connection(URL, Options) -> any()` - -Equivalent to [`server_connection(Host, Port, "", [])`](#server_connection-4). - -Create a server for connectiong to a CouchDB node - - - -### server_connection/4 ### - -

-server_connection(Host::string(), Port::non_neg_integer(), Prefix::string(), OptionsList::list()) -> Server::server()
-
-
- -Create a server for connectiong to a CouchDB node - -Connections are made to: - -``` - http://Host:PortPrefix -``` - -If ssl is set https is used. - -For a description of SSL Options, look in the [ssl](http://www.erlang.org/doc/apps/ssl/index.html) manpage. - - - -### server_info/1 ### - -

-server_info(Server::server()) -> {ok, iolist()}
-
-
- -Get Information from the server - - - -### stream_attachment/1 ### - -

-stream_attachment(Ref::atom()) -> {ok, binary()} | done | {error, term()}
-
-
- -fetch an attachment chunk. -Use this function when you pass the `stream` option to the -`couchbeam:fetch_attachment/4` function. -This function return the following response: - - - -
done
- - - - -
You got all the attachment
- - - - -
{ok, binary()}
- - - - -
Part of the attachment
- - - - -
{error, term()}
- - - - -
n error occurred
- - - - - - -### stream_doc/1 ### - -

-stream_doc(X1::doc_stream()) -> {doc, doc()} | {att, Name::binary(), doc_stream()} | {att_body, Name::binary(), Chunk::binary(), doc_stream()} | {att_eof, Name::binary(), doc_stream()} | eof | {error, term()}
-
-
- -stream the multipart response of the doc API. Use this function -when you get `{ok, {multipart, State}}` from the function -`couchbeam:open_doc/3`. - - - -### view_cleanup/1 ### - -`view_cleanup(Db) -> any()` - diff --git a/doc/couchbeam_app.md b/doc/couchbeam_app.md deleted file mode 100644 index 40b0c2f3..00000000 --- a/doc/couchbeam_app.md +++ /dev/null @@ -1,32 +0,0 @@ - - -# Module couchbeam_app # -* [Function Index](#index) -* [Function Details](#functions) - -__Behaviours:__ [`application`](application.md). - - - -## Function Index ## - - -
start/2
stop/1
- - - - -## Function Details ## - - - -### start/2 ### - -`start(Type, StartArgs) -> any()` - - - -### stop/1 ### - -`stop(State) -> any()` - diff --git a/doc/couchbeam_attachments.md b/doc/couchbeam_attachments.md deleted file mode 100644 index ea3fb7cc..00000000 --- a/doc/couchbeam_attachments.md +++ /dev/null @@ -1,61 +0,0 @@ - - -# Module couchbeam_attachments # -* [Description](#description) -* [Function Index](#index) -* [Function Details](#functions) - -This module contains utilities to manage attachments. - - - -## Function Index ## - - -
add_inline/3add attachment to a doc and encode it.
add_inline/4add attachment to a doc and encode it with ContentType fixed.
add_stub/3
delete_inline/2delete an attachment record in doc.
- - - - -## Function Details ## - - - -### add_inline/3 ### - -

-add_inline(Doc::json_obj(), Content::attachment_content(), AName::string()) -> json_obj()
-
-
- -add attachment to a doc and encode it. Give possibility to send attachments inline. - - - -### add_inline/4 ### - -

-add_inline(Doc::json_obj(), Content::attachment_content(), AName::string(), ContentType::string()) -> json_obj()
-
-
- -add attachment to a doc and encode it with ContentType fixed. - - - -### add_stub/3 ### - -`add_stub(Doc, Name, ContentType) -> any()` - - - -### delete_inline/2 ### - -

-delete_inline(Doc::json_obj(), AName::string()) -> json_obj()
-
-
- -delete an attachment record in doc. This is different from delete_attachment -change is only applied in Doc object. Save_doc should be save to save changes. - diff --git a/doc/couchbeam_changes.md b/doc/couchbeam_changes.md deleted file mode 100644 index 32c93f58..00000000 --- a/doc/couchbeam_changes.md +++ /dev/null @@ -1,206 +0,0 @@ - - -# Module couchbeam_changes # -* [Function Index](#index) -* [Function Details](#functions) - - - -## Function Index ## - - -
cancel_stream/1
follow/1
follow/2Stream changes to a pid.
follow_once/1
follow_once/2fetch all changes at once using a normal or longpoll -connections.
stream_next/1
- - - - -## Function Details ## - - - -### cancel_stream/1 ### - -`cancel_stream(Ref) -> any()` - - - -### follow/1 ### - -

-follow(Db::db()) -> {ok, StreamRef::atom()} | {error, term()}
-
-
- - - -### follow/2 ### - -

-follow(Db::db(), Options::changes_options()) -> {ok, StreamRef::atom()} | {error, term()}
-
-
- -Stream changes to a pid - -Db : a db record - -Client : pid or callback where to send changes events where events are -The pid receive these events: - - - -
{change, StartRef, {done, Lastseq::integer()}
- - - - -
Connection terminated or you got all changes
- - - - -
{change, StartRef, Row :: ejson_object()}
- - - - -
Line of change
- - - - -
{error, LastSeq::integer(), Msg::term()}
- - - - -
Got an error, connection is closed when an error -happend.
- - - -LastSeq is the last sequence of changes. - -While the callbac could be like: - -``` - - fun({done, LastSeq}) -> - ok; - fun({done, LastSeq}) -> - ok; - fun({done, LastSeq}) -> - ok. -``` - - -``` ->Options :: changes_stream_options() [continuous - | longpoll - | normal - | include_docs - | {since, integer() | now} - | {timeout, integer()} - | heartbeat | {heartbeat, integer()} - | {filter, string()} | {filter, string(), list({string(), string() | integer()})} - | {view, string()}, - | {docids, list))}, - | {stream_to, pid()}, - | {async, once | normal}] -``` - -* `continuous | longpoll | normal`: set the type of changes -feed to get - -* `include_doc`: if you want to include the doc in the line of -change - -* `{timeout, Timeout::integer()}`: timeout - -* `heartbeat | {heartbeat, Heartbeat::integer()}`: set couchdb -to send a heartbeat to maintain connection open - -* `{filter, FilterName} | {filter, FilterName, Args::list({key, -value})}`: set the filter to use with optional arguments - -* `{view, ViewName}`: use a view function as filter. Note -that it requires to set filter special value `"_view"` -to enable this feature. - -* >`{stream_to, Pid}`: the pid where the changes will be sent, -by default the current pid. Used for continuous and longpoll -connections - - -Return {ok, StartRef, ChangesPid} or {error, Error}. Ref can be -used to disctint all changes from this pid. ChangesPid is the pid of -the changes loop process. Can be used to monitor it or kill it -when needed. - - - -### follow_once/1 ### - -

-follow_once(Db::db()) -> {ok, LastSeq::integer(), Changes::list()} | {error, term()}
-
-
- - - -### follow_once/2 ### - -

-follow_once(Db::db(), Options::changes_options()) -> {ok, LastSeq::integer(), Changes::list()} | {error, term()}
-
-
- -fetch all changes at once using a normal or longpoll -connections. - -Db : a db record - -``` -Options :: changes_options() [ - | longpoll - | normal - | include_docs - | {since, integer() | now} - | {timeout, integer()} - | heartbeat | {heartbeat, integer()} - | {filter, string()} - | {filter, string(), list({string(), string() | integer()})} - | {docids, list()))}, - | {stream_to, pid()} - ] -``` - -* `longpoll | normal`: set the type of changes -feed to get - -* `include_docs`: if you want to include the doc in the line of -change - -* `{timeout, Timeout::integer()}`: timeout - -* `heartbeat | {heartbeat, Heartbeat::integer()}`: set couchdb -to send a heartbeat to maintain connection open - -* `{filter, FilterName} | {filter, FilterName, Args::list({key, -value})`: set the filter to use with optional arguments - -* `{view, ViewName}`: use a view function as filter. Note -that it requires to set filter special value `"_view"` -to enable this feature. - - -Result: `{ok, LastSeq::integer(), Rows::list()}` or -`{error, LastSeq, Error}`. LastSeq is the last sequence of changes. - - - -### stream_next/1 ### - -`stream_next(Ref) -> any()` - diff --git a/doc/couchbeam_changes_stream.md b/doc/couchbeam_changes_stream.md deleted file mode 100644 index 545ec862..00000000 --- a/doc/couchbeam_changes_stream.md +++ /dev/null @@ -1,99 +0,0 @@ - - -# Module couchbeam_changes_stream # -* [Function Index](#index) -* [Function Details](#functions) - - - -## Function Index ## - - -
collect_object/2
handle_event/2
init/1
init_stream/5
maybe_continue/1
maybe_continue_decoding/1
start_link/4
system_code_change/4
system_continue/3
system_terminate/4
wait_reconnect/1
wait_results/2
wait_results1/2
- - - - -## Function Details ## - - - -### collect_object/2 ### - -`collect_object(X1, X2) -> any()` - - - -### handle_event/2 ### - -`handle_event(Event, St) -> any()` - - - -### init/1 ### - -`init(X1) -> any()` - - - -### init_stream/5 ### - -`init_stream(Parent, Owner, StreamRef, Db, Options) -> any()` - - - -### maybe_continue/1 ### - -`maybe_continue(State) -> any()` - - - -### maybe_continue_decoding/1 ### - -`maybe_continue_decoding(State) -> any()` - - - -### start_link/4 ### - -`start_link(Owner, StreamRef, Db, Options) -> any()` - - - -### system_code_change/4 ### - -`system_code_change(Misc, X2, X3, X4) -> any()` - - - -### system_continue/3 ### - -`system_continue(X1, X2, X3) -> any()` - - - -### system_terminate/4 ### - -

-system_terminate(Reason::any(), X2::term(), X3::term(), State::term()) -> no_return()
-
-
- - - -### wait_reconnect/1 ### - -`wait_reconnect(State) -> any()` - - - -### wait_results/2 ### - -`wait_results(X1, St) -> any()` - - - -### wait_results1/2 ### - -`wait_results1(X1, X2) -> any()` - diff --git a/doc/couchbeam_changes_sup.md b/doc/couchbeam_changes_sup.md deleted file mode 100644 index dd397ac4..00000000 --- a/doc/couchbeam_changes_sup.md +++ /dev/null @@ -1,35 +0,0 @@ - - -# Module couchbeam_changes_sup # -* [Function Index](#index) -* [Function Details](#functions) - -__Behaviours:__ [`supervisor`](supervisor.md). - - - -## Function Index ## - - -
init/1
start_link/0
- - - - -## Function Details ## - - - -### init/1 ### - -`init(X1) -> any()` - - - -### start_link/0 ### - -

-start_link() -> {ok, pid()}
-
-
- diff --git a/doc/couchbeam_deps.md b/doc/couchbeam_deps.md deleted file mode 100644 index a1707379..00000000 --- a/doc/couchbeam_deps.md +++ /dev/null @@ -1,117 +0,0 @@ - - -# Module couchbeam_deps # -* [Function Index](#index) -* [Function Details](#functions) - - - - -## Function Index ## - - -
deps_on_path/0List of project dependencies on the path.
ensure/0Ensure that the ebin and include paths for dependencies of -this application are on the code path.
ensure/1Ensure that all ebin and include paths for dependencies -of the application for Module are on the code path.
get_base_dir/0Return the application directory for this application.
get_base_dir/1Return the application directory for Module.
local_path/1Return an application-relative directory for this application.
local_path/2Return an application-relative directory from Module's application.
new_siblings/1Find new siblings paths relative to Module that aren't already on the -code path.
- - - - -## Function Details ## - - - -### deps_on_path/0 ### - - -

-deps_on_path() -> [ProjNameAndVers]
-
-
- -List of project dependencies on the path. - - -### ensure/0 ### - - -

-ensure() -> ok
-
-
- -Ensure that the ebin and include paths for dependencies of -this application are on the code path. Equivalent to -ensure(?Module). - - -### ensure/1 ### - - -

-ensure(Module) -> ok
-
-
- -Ensure that all ebin and include paths for dependencies -of the application for Module are on the code path. - - -### get_base_dir/0 ### - - -

-get_base_dir() -> string()
-
-
- -Return the application directory for this application. Equivalent to -get_base_dir(?MODULE). - - -### get_base_dir/1 ### - - -

-get_base_dir(Module) -> string()
-
-
- -Return the application directory for Module. It assumes Module is in -a standard OTP layout application in the ebin or src directory. - - -### local_path/1 ### - - -

-local_path(Components) -> string()
-
-
- -Return an application-relative directory for this application. -Equivalent to local_path(Components, ?MODULE). - - -### local_path/2 ### - - -

-local_path(Components::[string()], Module) -> string()
-
-
- -Return an application-relative directory from Module's application. - - -### new_siblings/1 ### - - -

-new_siblings(Module) -> [Dir]
-
-
- -Find new siblings paths relative to Module that aren't already on the -code path. diff --git a/doc/couchbeam_doc.md b/doc/couchbeam_doc.md deleted file mode 100644 index df26b826..00000000 --- a/doc/couchbeam_doc.md +++ /dev/null @@ -1,187 +0,0 @@ - - -# Module couchbeam_doc # -* [Data Types](#types) -* [Function Index](#index) -* [Function Details](#functions) - - - -## Data Types ## - - - - -### key_val() ### - - -

-key_val() = lis() | binary()
-
- - - - -### property() ### - - -

-property() = json_obj() | tuple()
-
- - - -## Function Index ## - - -
delete_value/2Deletes all entries associated with Key in json object.
extend/2extend a jsonobject by a property, list of property or another jsonobject.
extend/3extend a jsonobject by key, value.
get_id/1get document id.
get_idrev/1get a tuple containing docucment id and revision.
get_rev/1get document revision.
get_value/2Returns the value of a simple key/value property in json object -Equivalent to get_value(Key, JsonObj, undefined).
get_value/3Returns the value of a simple key/value property in json object -function from erlang_couchdb.
is_saved/1If document have been saved (revision is defined) return true, -else, return false.
set_value/3set a value for a key in jsonobj.
take_value/2Returns the value of a simple key/value property in json object and deletes -it form json object -Equivalent to take_value(Key, JsonObj, undefined).
take_value/3Returns the value of a simple key/value property in json object and deletes -it from json object.
- - - - -## Function Details ## - - - -### delete_value/2 ### - -

-delete_value(Key::key_val(), JsonObj::json_obj()) -> json_obj()
-
-
- -Deletes all entries associated with Key in json object. - - - -### extend/2 ### - -

-extend(Prop::property(), JsonObj::json_obj()) -> json_obj()
-
-
- -extend a jsonobject by a property, list of property or another jsonobject - - - -### extend/3 ### - -

-extend(Key::binary(), Value::json_term(), JsonObj::json_obj()) -> json_obj()
-
-
- -extend a jsonobject by key, value - - - -### get_id/1 ### - -

-get_id(Doc::json_obj()) -> binary()
-
-
- -get document id. - - - -### get_idrev/1 ### - -

-get_idrev(Doc::json_obj()) -> {DocId, DocRev}
-
-
- -get a tuple containing docucment id and revision. - - - -### get_rev/1 ### - -

-get_rev(Doc::json_obj()) -> binary()
-
-
- -get document revision. - - - -### get_value/2 ### - -

-get_value(Key::key_val(), JsonObj::json_obj()) -> term()
-
-
- -Returns the value of a simple key/value property in json object -Equivalent to get_value(Key, JsonObj, undefined). - - - -### get_value/3 ### - -

-get_value(Key::lis() | binary(), JsonObj::json_obj(), Default::term()) -> term()
-
-
- -Returns the value of a simple key/value property in json object -function from erlang_couchdb - - - -### is_saved/1 ### - -

-is_saved(Doc::json_obj()) -> boolean()
-
-
- -If document have been saved (revision is defined) return true, -else, return false. - - - -### set_value/3 ### - -

-set_value(Key::key_val(), Value::term(), JsonObj::json_obj()) -> term()
-
-
- -set a value for a key in jsonobj. If key exists it will be updated. - - - -### take_value/2 ### - -

-take_value(Key::key_val(), JsonObj::json_obj()) -> {term(), json_obj()}
-
-
- -Returns the value of a simple key/value property in json object and deletes -it form json object -Equivalent to take_value(Key, JsonObj, undefined). - - - -### take_value/3 ### - -

-take_value(Key::key_val() | binary(), JsonObj::json_obj(), Default::term()) -> {term(), json_obj()}
-
-
- -Returns the value of a simple key/value property in json object and deletes -it from json object - diff --git a/doc/couchbeam_ejson.md b/doc/couchbeam_ejson.md deleted file mode 100644 index 80862c4c..00000000 --- a/doc/couchbeam_ejson.md +++ /dev/null @@ -1,48 +0,0 @@ - - -# Module couchbeam_ejson # -* [Function Index](#index) -* [Function Details](#functions) - - - -## Function Index ## - - -
decode/1decode a binary to an EJSON term.
encode/1encode an erlang term to JSON.
post_decode/1
- - - - -## Function Details ## - - - -### decode/1 ### - -

-decode(D::binary()) -> ejson()
-
-
- -decode a binary to an EJSON term. Throw an exception if there is -any error. - - - -### encode/1 ### - -

-encode(D::ejson()) -> binary()
-
-
- -encode an erlang term to JSON. Throw an exception if there is -any error. - - - -### post_decode/1 ### - -`post_decode(Rest) -> any()` - diff --git a/doc/couchbeam_httpc.md b/doc/couchbeam_httpc.md deleted file mode 100644 index b79ead95..00000000 --- a/doc/couchbeam_httpc.md +++ /dev/null @@ -1,83 +0,0 @@ - - -# Module couchbeam_httpc # -* [Function Index](#index) -* [Function Details](#functions) - - - -## Function Index ## - - -
db_request/5
db_request/6
db_resp/2
db_url/1
doc_url/2
json_body/1
make_headers/4
maybe_oauth_header/4
request/5
server_url/1Asemble the server URL for the given client.
- - - - -## Function Details ## - - - -### db_request/5 ### - -`db_request(Method, Url, Headers, Body, Options) -> any()` - - - -### db_request/6 ### - -`db_request(Method, Url, Headers, Body, Options, Expect) -> any()` - - - -### db_resp/2 ### - -`db_resp(Resp, Expect) -> any()` - - - -### db_url/1 ### - -`db_url(Db) -> any()` - - - -### doc_url/2 ### - -`doc_url(Db, DocId) -> any()` - - - -### json_body/1 ### - -`json_body(Ref) -> any()` - - - -### make_headers/4 ### - -`make_headers(Method, Url, Headers, Options) -> any()` - - - -### maybe_oauth_header/4 ### - -`maybe_oauth_header(Method, Url, Headers, Options) -> any()` - - - -### request/5 ### - -`request(Method, Url, Headers, Body, Options) -> any()` - - - -### server_url/1 ### - -

-server_url(Server::{Host, Port}) -> iolist()
-
-
- -Asemble the server URL for the given client - diff --git a/doc/couchbeam_sup.md b/doc/couchbeam_sup.md deleted file mode 100644 index 0435f6d1..00000000 --- a/doc/couchbeam_sup.md +++ /dev/null @@ -1,32 +0,0 @@ - - -# Module couchbeam_sup # -* [Function Index](#index) -* [Function Details](#functions) - -__Behaviours:__ [`supervisor`](supervisor.md). - - - -## Function Index ## - - -
init/1
start_link/0
- - - - -## Function Details ## - - - -### init/1 ### - -`init(X1) -> any()` - - - -### start_link/0 ### - -`start_link() -> any()` - diff --git a/doc/couchbeam_util.md b/doc/couchbeam_util.md deleted file mode 100644 index ddcaaa87..00000000 --- a/doc/couchbeam_util.md +++ /dev/null @@ -1,202 +0,0 @@ - - -# Module couchbeam_util # -* [Function Index](#index) -* [Function Details](#functions) - - - -## Function Index ## - - -
binary_env/2
dbname/1
deprecated/3
encode_att_name/1
encode_docid/1
encode_docid1/1
encode_docid_noop/1
encode_query/1Encode needed query parameter values for JSON.
encode_query_value/2Encode value in JSON if needed depending on the key.
force_param/3Replace a value in a property list.
get_app_env/2
get_value/2Emulate proplists:get_value/2,3 for property lists using lists:keyfind/3.
get_value/3
oauth_header/3
parse_options/1make view options a list.
parse_options/2
propmerge/3Merge two property lists.
propmerge1/2Update a property list with values of the second.
proxy_header/3
proxy_token/2
shutdown_sync/1
start_app_deps/1Start depedent applications of App.
to_atom/1
to_binary/1
to_integer/1
to_list/1
- - - - -## Function Details ## - - - -### binary_env/2 ### - -`binary_env(Key, Default) -> any()` - - - -### dbname/1 ### - -`dbname(DbName) -> any()` - - - -### deprecated/3 ### - -`deprecated(Old, New, When) -> any()` - - - -### encode_att_name/1 ### - -`encode_att_name(Name) -> any()` - - - -### encode_docid/1 ### - -`encode_docid(DocId) -> any()` - - - -### encode_docid1/1 ### - -`encode_docid1(DocId) -> any()` - - - -### encode_docid_noop/1 ### - -`encode_docid_noop(DocId) -> any()` - - - -### encode_query/1 ### - -`encode_query(QSL) -> any()` - -Encode needed query parameter values for JSON - - - -### encode_query_value/2 ### - -`encode_query_value(K, V) -> any()` - -Encode value in JSON if needed depending on the key - - - -### force_param/3 ### - -`force_param(Key, Value, Options) -> any()` - -Replace a value in a property list - - - -### get_app_env/2 ### - -`get_app_env(Env, Default) -> any()` - - - -### get_value/2 ### - -

-get_value(Key::term(), Prop::[term()]) -> term()
-
-
- -Emulate proplists:get_value/2,3 for property lists using faster lists:keyfind/3 - - - -### get_value/3 ### - -

-get_value(Key::term(), Prop::[term()], Default::term()) -> term()
-
-
- - - -### oauth_header/3 ### - -`oauth_header(Url, Action, OauthProps) -> any()` - - - -### parse_options/1 ### - -`parse_options(Options) -> any()` - -make view options a list - - - -### parse_options/2 ### - -`parse_options(Rest, Acc) -> any()` - - - -### propmerge/3 ### - -`propmerge(F, L1, L2) -> any()` - -Merge two property lists (lists of {Key,Value}). All the Key - Value pairs from both lists -are included in the new list. If a key occurs in both dictionaries -then Fun is called with the key and both values to return a new -value. This a wreapper around dict:merge - - - -### propmerge1/2 ### - -`propmerge1(L1, L2) -> any()` - -Update a property list with values of the second. In case the same -key is in both lists, the value from the first is kept. - - - -### proxy_header/3 ### - -`proxy_header(UserName, Roles, Secret) -> any()` - - - -### proxy_token/2 ### - -`proxy_token(Secret, UserName) -> any()` - - - -### shutdown_sync/1 ### - -`shutdown_sync(Pid) -> any()` - - - -### start_app_deps/1 ### - -

-start_app_deps(App::atom()) -> ok
-
-
- -Start depedent applications of App. - - - -### to_atom/1 ### - -`to_atom(V) -> any()` - - - -### to_binary/1 ### - -`to_binary(V) -> any()` - - - -### to_integer/1 ### - -`to_integer(V) -> any()` - - - -### to_list/1 ### - -`to_list(V) -> any()` diff --git a/doc/couchbeam_uuids.md b/doc/couchbeam_uuids.md deleted file mode 100644 index 43c1e4e5..00000000 --- a/doc/couchbeam_uuids.md +++ /dev/null @@ -1,95 +0,0 @@ - - -# Module couchbeam_uuids # -* [Function Index](#index) -* [Function Details](#functions) - -__Behaviours:__ [`gen_server`](gen_server.md). - - - -## Function Index ## - - -
code_change/3
get_uuids/2Get a list of uuids from the server.
handle_call/3
handle_cast/2
handle_info/2
random/0return a random uuid.
start_link/0Starts the couchbeam process linked to the calling process.
terminate/2
utc_random/0return a random uuid based on time.
- - - - -## Function Details ## - - - -### code_change/3 ### - -`code_change(OldVsn, State, Extra) -> any()` - - - -### get_uuids/2 ### - -

-get_uuids(Server::server(), Count::integer()) -> lists()
-
-
- -Get a list of uuids from the server - - - -### handle_call/3 ### - -`handle_call(X1, From, State) -> any()` - - - -### handle_cast/2 ### - -`handle_cast(Msg, State) -> any()` - - - -### handle_info/2 ### - -`handle_info(Info, State) -> any()` - - - -### random/0 ### - -

-random() -> binary()
-
-
- -return a random uuid - - - -### start_link/0 ### - -

-start_link() -> {ok, pid()}
-
-
- -Starts the couchbeam process linked to the calling process. Usually -invoked by the supervisor couchbeam_sup - - - -### terminate/2 ### - -`terminate(Reason, State) -> any()` - - - -### utc_random/0 ### - -

-utc_random() -> binary()
-
-
- -return a random uuid based on time - diff --git a/doc/couchbeam_view.md b/doc/couchbeam_view.md deleted file mode 100644 index d8ce7394..00000000 --- a/doc/couchbeam_view.md +++ /dev/null @@ -1,402 +0,0 @@ - - -# Module couchbeam_view # -* [Function Index](#index) -* [Function Details](#functions) - - - -## Function Index ## - - -
all/1fetch all docs.
all/2fetch all docs.
cancel_stream/1
count/1Equivalent to count(Db, all_docs, []).
count/2Equivalent to count(Db, ViewName, []).
count/3count number of doc in a view (or all docs).
fetch/1Equivalent to fetch(Db, all_docs, []).
fetch/2Equivalent to fetch(Db, ViewName, []).
fetch/3Collect view results.
first/1Equivalent to first(Db, all_docs, []).
first/2Equivalent to first(Db, ViewName, []).
first/3get first result of a view.
fold/4Equivalent to fold(Function, Acc, Db, ViewName, []).
fold/5call Function(Row, AccIn) on succesive row, starting with -AccIn == Acc.
foreach/3Equivalent to foreach(Function, Db, ViewName, []).
foreach/4call Function(Row) on succesive row.
parse_view_options/1parse view options.
stream/2Equivalent to stream(Db, ViewName, Client, []).
stream/3stream view results to a pid.
stream_next/1
- - - - -## Function Details ## - - - -### all/1 ### - -

-all(Db::db()) -> {ok, Rows::[ejson_object()]} | {error, term()}
-
-
- -Equivalent to [`fetch(Db, all_docs, [])`](#fetch-3). - -fetch all docs - - - -### all/2 ### - -

-all(Db::db(), Options::view_options()) -> {ok, Rows::[ejson_object()]} | {error, term()}
-
-
- -Equivalent to [`fetch(Db, all_docs, Options)`](#fetch-3). - -fetch all docs - - - -### cancel_stream/1 ### - -`cancel_stream(Ref) -> any()` - - - -### count/1 ### - -

-count(Db::db()) -> integer() | {error, term()}
-
-
- -Equivalent to [`count(Db, all_docs, [])`](#count-3). - - - -### count/2 ### - -

-count(Db::db(), ViewName::all_docs | {DesignName::design_name(), ViewName::view_name()}) -> integer() | {error, term()}
-
-
- -Equivalent to [`count(Db, ViewName, [])`](#count-3). - - - -### count/3 ### - -

-count(Db::db(), ViewName::all_docs | {DesignName::design_name(), ViewName::view_name()}, Options::view_options()) -> integer() | {error, term()}
-
-
- -count number of doc in a view (or all docs) - - - -### fetch/1 ### - -

-fetch(Db::db()) -> {ok, Rows::[ejson_object()]} | {error, term()}
-
-
- -Equivalent to [`fetch(Db, all_docs, [])`](#fetch-3). - - - -### fetch/2 ### - -

-fetch(Db::db(), ViewName::all_docs | {DesignName::design_name(), ViewName::view_name()}) -> {ok, Rows::[ejson_object()]} | {error, term()}
-
-
- -Equivalent to [`fetch(Db, ViewName, [])`](#fetch-3). - - - -### fetch/3 ### - -

-fetch(Db::db(), ViewName::all_docs | {DesignName::design_name(), ViewName::view_name()}, Options::view_options()) -> {ok, Rows::[ejson_object()]} | {error, term()}
-
-
- -Collect view results - -Db: a db record - -ViewName: `'all_docs'` to get all docs or `{DesignName, -ViewName}` - - -``` -Options :: view_options() [{key, binary()} - | {start_docid, binary()} | {startkey_docid, binary()} - | {end_docid, binary()} | {endkey_docid, binary()} - | {start_key, binary()} | {end_key, binary()} - | {limit, integer()} - | {stale, stale()} - | descending - | {skip, integer()} - | group | {group_level, integer()} - | {inclusive_end, boolean()} | {reduce, boolean()} | reduce | include_docs | conflicts - | {keys, list(binary())} -``` - - -See [`couchbeam_view:stream/4`](couchbeam_view.md#stream-4) for more information about -options. - -Return: {ok, Rows} or {error, Error} - - - -### first/1 ### - -

-first(Db::db()) -> {ok, Row::ejson_object()} | {error, term()}
-
-
- -Equivalent to [`first(Db, all_docs, [])`](#first-3). - - - -### first/2 ### - -

-first(Db::db(), ViewName::all_docs | {DesignName::design_name(), ViewName::view_name()}) -> {ok, Row::ejson_object()} | {error, term()}
-
-
- -Equivalent to [`first(Db, ViewName, [])`](#first-3). - - - -### first/3 ### - -

-first(Db::db(), ViewName::all_docs | {DesignName::design_name(), ViewName::view_name()}, Options::view_options()) -> {ok, Rows::ejson_object()} | {error, term()}
-
-
- -get first result of a view - -Db: a db record - -ViewName: 'all_docs' to get all docs or {DesignName, -ViewName} - - -``` -Options :: view_options() [{key, binary()} - | {start_docid, binary()} | {startkey_docid, binary()} - | {end_docid, binary()} | {endkey_docid, binary()} - | {start_key, binary()} | {end_key, binary()} - | {limit, integer()} - | {stale, stale()} - | descending - | {skip, integer()} - | group | {group_level, integer()} - | {inclusive_end, boolean()} | {reduce, boolean()} | reduce | include_docs | conflicts - | {keys, list(binary())} -``` - - -See [`couchbeam_view:stream/4`](couchbeam_view.md#stream-4) for more information about -options. - -Return: {ok, Row} or {error, Error} - - - -### fold/4 ### - -

-fold(Function::function(), Acc::any(), Db::db(), ViewName::all_docs | {DesignName::design_name(), ViewName::view_name()}) -> [term()] | {error, term()}
-
-
- -Equivalent to [`fold(Function, Acc, Db, ViewName, [])`](#fold-5). - - - -### fold/5 ### - -

-fold(Function::function(), Acc::any(), Db::db(), ViewName::all_docs | {DesignName::design_name(), ViewName::view_name()}, Options::view_options()) -> [term()] | {error, term()}
-
-
- -call Function(Row, AccIn) on succesive row, starting with -AccIn == Acc. Function/2 must return a new list accumultator or the -atom _done_ to stop fetching results. Acc0 is returned if the -list is empty. For example: - -``` - couchbeam_view:fold(fun(Row, Acc) -> [Row|Acc] end, [], Db, 'all_docs'). -``` - - - -### foreach/3 ### - -

-foreach(Function::function(), Db::db(), ViewName::all_docs | {DesignName::design_name(), ViewName::view_name()}) -> [term()] | {error, term()}
-
-
- -Equivalent to [`foreach(Function, Db, ViewName, [])`](#foreach-4). - - - -### foreach/4 ### - -

-foreach(Function::function(), Db::db(), ViewName::all_docs | {DesignName::design_name(), ViewName::view_name()}, Options::view_options()) -> [term()] | {error, term()}
-
-
- -call Function(Row) on succesive row. Example: - -``` - couchbeam_view:foreach(fun(Row) -> io:format("got row ~p~n", [Row]) end, Db, 'all_docs'). -``` - - - -### parse_view_options/1 ### - -

-parse_view_options(Options::list()) -> view_query_args()
-
-
- -parse view options - - - -### stream/2 ### - -

-stream(Db::db(), ViewName::all_docs | {DesignName::design_name(), ViewName::view_name()}) -> {ok, StartRef::term(), ViewPid::pid()} | {error, term()}
-
-
- -Equivalent to [`stream(Db, ViewName, Client, [])`](#stream-4). - - - -### stream/3 ### - -

-stream(Db::db(), ViewName::all_docs | {DesignName::design_name(), ViewName::view_name()}, Options::view_options()) -> {ok, StartRef::term()} | {error, term()}
-
-
- -stream view results to a pid - -Db: a db record - -ViewName: 'all_docs' to get all docs or {DesignName, -ViewName} - -Client: pid where to send view events where events are: - - - -
{row, StartRef, done}
- - - - -
All view results have been fetched
- - - - -
{row, StartRef, Row :: ejson_object()}
- - - - -
A row in the view
- - - - -
{error, StartRef, Error}
- - - - -
Got an error, connection is closed when an error -happend.
- - - -``` -Options :: view_options() [{key, binary()} - | {start_docid, binary()} | {startkey_docid, binary()} - | {end_docid, binary()} | {endkey_docid, binary()} - | {start_key, binary()} | {end_key, binary()} - | {limit, integer()} - | {stale, stale()} - | descending - | {skip, integer()} - | group | {group_level, integer()} - | {inclusive_end, boolean()} | {reduce, boolean()} | reduce | include_docs | conflicts - | {keys, list(binary())} - | {stream_to, Pid}: the pid where the changes will be sent, - by default the current pid. Used for continuous and longpoll - connections -``` - -* `{key, Key}`: key value - -* `{start_docid, DocId}` | `{startkey_docid, DocId}`: document id to start with (to allow pagination -for duplicate start keys - -* `{end_docid, DocId}` | `{endkey_docid, DocId}`: last document id to include in the result (to -allow pagination for duplicate endkeys) - -* `{start_key, Key}`: start result from key value - -* `{end_key, Key}`: end result from key value - -* `{limit, Limit}`: Limit the number of documents in the result - -* `{stale, Stale}`: If stale=ok is set, CouchDB will not refresh the view -even if it is stale, the benefit is a an improved query latency. If -stale=update_after is set, CouchDB will update the view after the stale -result is returned. If stale=false is set, CouchDB will update the view before -the query. The default value of this parameter is update_after. - -* `descending`: reverse the result - -* `{skip, N}`: skip n number of documents - -* `group`: the reduce function reduces to a single result -row. - -* `{group_level, Level}`: the reduce function reduces to a set -of distinct keys. - -* `{reduce, boolean()}`: whether to use the reduce function of the view. It defaults to -true, if a reduce function is defined and to false otherwise. - -* `include_docs`: automatically fetch and include the document -which emitted each view entry - -* `{inclusive_end, boolean()}`: Controls whether the endkey is included in -the result. It defaults to true. - -* `conflicts`: include conflicts - -* `{keys, [Keys]}`: to pass multiple keys to the view query - - -Return `{ok, StartRef, ViewPid}` or `{error, -Error}`. Ref can be -used to disctint all changes from this pid. ViewPid is the pid of -the view loop process. Can be used to monitor it or kill it -when needed. - - - -### stream_next/1 ### - -`stream_next(Ref) -> any()` - diff --git a/doc/couchbeam_view_stream.md b/doc/couchbeam_view_stream.md deleted file mode 100644 index 13614756..00000000 --- a/doc/couchbeam_view_stream.md +++ /dev/null @@ -1,99 +0,0 @@ - - -# Module couchbeam_view_stream # -* [Function Index](#index) -* [Function Details](#functions) - - - -## Function Index ## - - -
collect_object/2
handle_event/2
init/1
init_stream/5
maybe_continue/1
maybe_continue_decoding/1
start_link/4
system_code_change/4
system_continue/3
system_terminate/4
wait_rows/2
wait_rows1/2
wait_val/2
- - - - -## Function Details ## - - - -### collect_object/2 ### - -`collect_object(X1, X2) -> any()` - - - -### handle_event/2 ### - -`handle_event(Event, St) -> any()` - - - -### init/1 ### - -`init(X1) -> any()` - - - -### init_stream/5 ### - -`init_stream(Parent, Owner, StreamRef, Req, StreamOptions) -> any()` - - - -### maybe_continue/1 ### - -`maybe_continue(State) -> any()` - - - -### maybe_continue_decoding/1 ### - -`maybe_continue_decoding(Viewst) -> any()` - - - -### start_link/4 ### - -`start_link(Owner, StreamRef, X3, StreamOptions) -> any()` - - - -### system_code_change/4 ### - -`system_code_change(Misc, X2, X3, X4) -> any()` - - - -### system_continue/3 ### - -`system_continue(X1, X2, X3) -> any()` - - - -### system_terminate/4 ### - -

-system_terminate(Reason::any(), X2::term(), X3::term(), State::term()) -> no_return()
-
-
- - - -### wait_rows/2 ### - -`wait_rows(X1, St) -> any()` - - - -### wait_rows1/2 ### - -`wait_rows1(X1, X2) -> any()` - - - -### wait_val/2 ### - -`wait_val(X1, X2) -> any()` - diff --git a/doc/couchbeam_view_sup.md b/doc/couchbeam_view_sup.md deleted file mode 100644 index 30f6f7fe..00000000 --- a/doc/couchbeam_view_sup.md +++ /dev/null @@ -1,35 +0,0 @@ - - -# Module couchbeam_view_sup # -* [Function Index](#index) -* [Function Details](#functions) - -__Behaviours:__ [`supervisor`](supervisor.md). - - - -## Function Index ## - - -
init/1
start_link/0
- - - - -## Function Details ## - - - -### init/1 ### - -`init(X1) -> any()` - - - -### start_link/0 ### - -

-start_link() -> {ok, pid()}
-
-
- diff --git a/doc/gen_changes.md b/doc/gen_changes.md deleted file mode 100644 index b7e1576d..00000000 --- a/doc/gen_changes.md +++ /dev/null @@ -1,110 +0,0 @@ - - -# Module gen_changes # -* [Description](#description) -* [Function Index](#index) -* [Function Details](#functions) - -gen_changes CouchDB continuous changes consumer behavior -This behaviour allows you to create easily a server that consume -Couchdb continuous changes. - -__This module defines the `gen_changes` behaviour.__
Required callback functions: `init/1`, `handle_change/2`, `handle_call/3`, `handle_cast/2`, `handle_info/2`, `terminate/2`. - - - -## Function Index ## - - -
behaviour_info/1
call/2
call/3
cast/2
code_change/3
get_seq/1
handle_call/3
handle_cast/2
handle_info/2
init/1
start_link/4create a gen_changes process as part of a supervision tree.
stop/1
terminate/2
- - - - -## Function Details ## - - - -### behaviour_info/1 ### - -`behaviour_info(X1) -> any()` - - - -### call/2 ### - -`call(Name, Request) -> any()` - - - -### call/3 ### - -`call(Name, Request, Timeout) -> any()` - - - -### cast/2 ### - -`cast(Dest, Request) -> any()` - - - -### code_change/3 ### - -`code_change(OldVersion, State, Extra) -> any()` - - - -### get_seq/1 ### - -`get_seq(Pid) -> any()` - - - -### handle_call/3 ### - -`handle_call(Request, From, State) -> any()` - - - -### handle_cast/2 ### - -`handle_cast(Msg, State) -> any()` - - - -### handle_info/2 ### - -`handle_info(Info, State) -> any()` - - - -### init/1 ### - -`init(X1) -> any()` - - - -### start_link/4 ### - -

-start_link(Module, Db::db(), Options::changesoptions(), InitArgs::list()) -> term()
-
- - - -create a gen_changes process as part of a supervision tree. -The function should be called, directly or indirectly, by the supervisor. - - - -### stop/1 ### - -`stop(Pid) -> any()` - - - -### terminate/2 ### - -`terminate(Reason, Gen_changes_state) -> any()` - diff --git a/doc/overview.edoc b/doc/overview.edoc deleted file mode 100644 index f86101df..00000000 --- a/doc/overview.edoc +++ /dev/null @@ -1,390 +0,0 @@ -%% -*- erlang -*- -%% -%% This file is part of couchbeam released under the MIT license. -%% See the NOTICE for more information. - - - -@copyright 2009-2025 Benoît Chesneau. -@version 1.5.4 -@title Couchbeam - simple Apache CouchDB client library for Erlang applications - -@doc - -# couchbeam - -Couchbeam is a simple erlang library for [Barrel](https://barrel-db.org) or [Apache CouchDB](http://couchdb.apache.org). Couchbeam provides you a full featured and easy client to access and manage multiple nodes. - -#### Main features: - -- Complete support of the BarrelDB and Apache CouchDB API -- Stream view results to your app -- Stream changes feeds -- reduced memory usage -- fetch and send attachments in a streaming fashion -- by default use the JSX module to encode/decode JSON -- support [Jiffy](http://github.com/davisp/jiffy) a JSON encoder/decoder - in C. - - -#### Useful modules are: - -- {@link couchbeam}: The `couchbeam' module is the main interface for interaction with this application. It includes functions for managing connections to Apache CouchDB or RCOUCH servers and databases and for performing document creations, updates, deletes, views... -- {@link couchbeam_doc} Module to manipulate Documents structures. You can set values, -updates keys, ... -- {@link couchbeam_attachments}: Module to manipulate attachments. You can add, remove -attachments in a Document structure (inline attachments). -- {@link couchbeam_view}: Module to manage view results. -- {@link couchbeam_changes}: Module to manage changes feeds. Follow continuously -the changes in a db or get all changes at once. - - -The goal of Couchbeam is to ease the access to the Apache CouchDB and RCOUCH HTTP API in erlang. - -Read the [NEWS](https://raw.github.com/benoitc/couchbeam/master/NEWS) file -to get last changelog. - -## Installation - -Download the sources from our [Github repository](http://github.com/benoitc/couchbeam) - -To build the application simply run 'make'. This should build .beam, .app -files and documentation. - -To run tests run 'make test'. -To generate doc, run 'make doc'. - - -Or add it to your rebar config - -```erlang -{deps, [ - .... - {couchbeam, ".*", {git, "git://github.com/benoitc/couchbeam.git", {branch, "master"}}} -]}. -''' - -Note to compile with jiffy you need to define in the erlang options the -variable `WITH_JIFFY'. - -if you use rebar, add to your `rebar.config': - -```erlang -{erl_opts, [{d, 'WITH_JIFFY'}]}. -''' - -or use the `rebar' command with the `-D' options: - -```sh -rebar compile -DWITH_JIFFY -''' - -## Basic Usage - -### Start couchbeam - -Couchbeam is an [OTP](http://www.erlang.org/doc/design_principles/users_guide.html) -application. You have to start it first before using any of the -functions. The couchbeam application will start the default socket pool -for you. - -To start in the console run: - - -```sh -$ erl -pa ebin -1> couchbeam:start(). -ok -''' - - -It will start hackney and all of the application it depends on: - -```erlang -application:start(crypto), -application:start(asn1), -application:start(public_key), -application:start(ssl), -application:start(hackney), -application:start(couchbeam). -''' - -Or add couchbeam to the applications property of your .app in a release - -### Create a connection to the server - -To create a connection to a server machine: - -```erlang -Url = "http://localhost:5984", -Options = [], -S = couchbeam:server_connection(Url, Options). -''' - -Test the connection with `couchbeam:server_info/1' : - -```erlang -{ok, _Version} = couchbeam:server_info(S). -''' - -### Open or Create a database - -All document operations are done in databases. To open a database simply do: - -```erlang -Options = [], -{ok, Db} = couchbeam:open_db(Server, "testdb", Options). -''' - -To create a new one: - -```erlang -Options = [], -{ok, Db} = couchbeam:create_db(Server, "testdb", Options). -''' - -You can also use the shorcut `couchbeam:open_or_create_db/3'. that -will create a database if it does not exist. - -### Make a new document - -Make a new document: - -```erlang -Doc = {[ -{<<"_id">>, <<"test">>}, -{<<"content">>, <<"some text">>} -]}. -''' - -And save it to the database: - -```erlang -{ok, Doc1} = couchbeam:save_doc(Db, Doc). -''' - -The `couchbeam:save_doc/2' return a new document with updated -revision and if you do not specify the _id, a unique document id. - -To change an document property use functions from `couchbeam_doc'. - -### Retrieve a document - -To retrieve a document do: - -```erlang -{ok, Doc2} = couchbeam:open_doc(Db, "test"). -''' - -If you want a specific revision: - -```erlang -Rev = couchbeam_doc:get_rev(Doc1), -Options = [{rev, Rev}], -{ok, Doc3} = couchbeam:open_doc(Db, "test", Options). -''' - -Here we get the revision from the document we previously stored. Any -options from the Apache CouchDB and RCOUCH API can be used. - -### Get all documents - -To get all documents you have first to create an object -that will keep all informations. - -```erlang -Options = [include_docs], -{ok, AllDocs} = couchbeam_view:all(Db, Options). -''' - - -Ex of results: - -```erlang -{ok,[{[{<<"id">>,<<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>}, - {<<"key">>,<<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>}, - {<<"value">>, - {[{<<"rev">>,<<"15-15c0b3c4efa74f9a80d28ac040f18bdb">>}]}}, - {<<"doc">>, - {[{<<"_id">>,<<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>}, - {<<"_rev">>,<<"15-15c0b3c4efa74f9a80d28ac040f18"...>>}]}}]}, - ]}. -''' - -All functions to manipulate these results are in the `couchbeam_view' module. - -### Couch DB views - -Views are workin like all_docs. You have to create a View object before -doing anything. - -```erlang -Options = [], -DesignName = "designname", -ViewName = "viewname", -{ok, ViewResults} = couchbeam_view:fetch(Db, {DesignName, ViewName}, Options). -''' - -Like the `all_docs' function, use the functions -from `couchbeam_view' module to manipulate results. You can pass -any querying options from the [view API](http://docs.rcouch.org/en/latest/api/ddoc/views.html). - -Design doc are created like any documents: - -```erlang -DesignDoc = {[ - {<<"_id">>, <<"_design/couchbeam">>}, - {<<"language">>,<<"javascript">>}, - {<<"views">>, - {[{<<"test">>, - {[{<<"map">>, - <<"function (doc) {\n if (doc.type == \"test\") {\n emit(doc._id, doc);\n}\n}">> - }]} - },{<<"test2">>, - {[{<<"map">>, - <<"function (doc) {\n if (doc.type == \"test2\") {\n emit(doc._id, null);\n}\n}">> - }]} - }]} - } - ]}, -{ok, DesignDoc1} = couchbeam:save_doc(Db, DesignDoc). -''' - -You can also use couchapp to manage them -more easily. - -### Stream View results - -While you can get results using `couchbeam_views:fetch/2', you can also retrieve -all rows in a streaming fashion: - -```erlang -ViewFun = fun(Ref, F) -> - receive - {Ref, done} -> - io:format("done", []), - done; - {Ref, {row, Row}} -> - io:format("got ~p~n", [Row]), - F(Ref, F); - {error, Ref, Error} -> - io:format("error: ~p~n", [Error]) - end -end, - -{ok, StreamRef} = couchbeam_view:stream(Db, 'all_docs'), -ViewFun(StreamRef, ViewFun), -{ok, StreamRef2} = couchbeam_view:stream(Db, 'all_docs', [include_docs]), -ViewFun(StreamRef2, ViewFun). -''' - -You can of course do the same with a view: - -```erlang -DesignNam = "designname", -ViewName = "viewname", -{ok, StreamRef3} = couchbeam_view:stream(Db, {DesignNam, ViewName}, [include_docs]), -ViewFun(StreamRef3, ViewFun). -''' - -### Put, Fetch and Delete documents attachments - -You can add attachments to any documents. Attachments could be anything. - -To send an attachment: - -```erlang -DocID = "test", -AttName = "test.txt", -Att = "some content I want to attach", -Options = [] -{ok, _Result} = couchbeam:put_attachment(Db, DocId, AttName, Att, Options). -''' - -All attachments are streamed to servers. `Att' could be also be an iolist -or functions, see `couchbeam:put_attachment/5' for more information. - -To fetch an attachment: - -```erlang -{ok Att1} = couchbeam:fetch_attachment(Db, DocId, AttName). -''' - -You can use `couchbeam:stream_fetch_attachment/6' for the stream -fetch. - -To delete an attachment: - -```erlang -{ok, Doc4} = couchbeam:open_doc(Db, DocID), -ok = couchbeam:delete_attachment(Db, Doc4, AttName). -''' - -### Changes - -Apache CouchDB and RCOUCH provide a means to get a list of changes made to documents in -the database. With couchbeam you can get changes using `couchbeam_changes:follow_once/2'. -This function returns all changes immediately. But you can also retrieve -all changes rows using longpolling : - -```erlang -Options = [], -{ok, LastSeq, Rows} = couchbeam_changes:follow_once(Db, Options). -''' - -Options can be any Changes query parameters. See the [change API](http://docs.rcouch.org/en/latest/api/database/changes.html) for more informations. - -You can also get [continuous](http://docs.rcouch.org/en/latest/api/database/changes.html#continuous): - -```erlang -ChangesFun = fun(StreamRef, F) -> - receive - {StreamRef, {done, LastSeq}} -> - io:format("stopped, last seq is ~p~n", [LastSeq]), - ok; - {StreamRef, {change, Change}} -> - io:format("change row ~p ~n", [Change]), - F(StreamRef, F); - {StreamRef, Error}-> - io:format("error ? ~p ~n,", [Error]) - end -end, -Options = [continuous, heartbeat], -{ok, StreamRef} = couchbeam_changes:follow(Db, Options), -ChangesFun(StreamRef, ChangesFun). -''' - -> **Note**: a `gen_changes' behaviour exists in couchbeam that you can -use to create your own specific gen_server receiving changes. Have a -look in the -[example](https://github.com/benoitc/couchbeam/blob/master/examples/test_gen_changes.erl) -for more info. - -### Authentication/ Connections options - -You can authenticate to the database or Apache CouchDB or RCOUCH server by filling -options to the Option list in `couchbeam:server_connection/4' for the -server or in `couchbeam:create_db/3', `couchbeam:open_db/3', -`couchbeam:wopen_or_create_db/3' functions. - -To set basic_auth on a server: - -```erlang -UserName = "guest", -Password = "test", -Url = "http://localhost:5984", -Options = [{basic_auth, {UserName, Password}}], -S1 = couchbeam:server_connection(Url, Options). -''' - -Couchbeam support SSL, OAuth, Basic Authentication, and Proxy. You can -also set a cookie. For more informations about the options have a look -in the `couchbeam:server_connection/2' documentation. - - -## Contribute - -For issues, comments or feedback please [create an -issue](http://github.com/benoitc/couchbeam/issues). - -@end diff --git a/include/couchbeam.hrl b/include/couchbeam.hrl index 47a2d518..b1f189d0 100644 --- a/include/couchbeam.hrl +++ b/include/couchbeam.hrl @@ -1,5 +1,5 @@ -%% @author Benoît Chesneau -%% @copyright 2009 Benoît Chesneau. +%% @author Benoit Chesneau +%% @copyright 2009-2025 Benoit Chesneau. %% %% %% Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/rebar.config b/rebar.config index cf3f2008..5f2a7cb1 100644 --- a/rebar.config +++ b/rebar.config @@ -4,21 +4,31 @@ {erl_opts, [debug_info, {platform_define, "^(2[3-9])", 'USE_CRYPTO_MAC'}]}. +%% ExDoc plugin for generating HTML docs +{plugins, [rebar3_ex_doc]}. + +%% ExDoc settings +{ex_doc, [ + {source_url, "https://github.com/benoitc/couchbeam"}, + {main, "readme"}, + {output, "site"}, + {extras, [ + {"README.md", #{title => "Readme"}}, + {"NEWS.md", #{title => "Changelog"}}, + {"NOTICE", #{title => "Notice"}}, + {"LICENSE", #{title => "License"}} + ]} +]}. + {deps, [ {hackney, "1.25.0"} ]}. -{profiles, [{docs, [{deps, [{edown,"0.9.1"}]}, - {edoc_opts, [{doclet, edown_doclet}, - {packages, false}, - {subpackages, true}, - {top_level_readme, - {"./README.md", "http://github.com/benoitc/couchbeam"}} - ]}]}, +{profiles, [ {test, [ - {cover_enabled, true}, - {eunit_opts, [verbose]}, - {deps, [{oauth, "2.1.0"}]} - ]} + {cover_enabled, true}, + {eunit_opts, [verbose]}, + {deps, [{oauth, "2.1.0"}]} + ]} ]}. diff --git a/site/.build b/site/.build new file mode 100644 index 00000000..79ca836f --- /dev/null +++ b/site/.build @@ -0,0 +1,34 @@ +404.html +api-reference.html +couchbeam.html +couchbeam_app.html +couchbeam_attachments.html +couchbeam_changes.html +couchbeam_changes_stream.html +couchbeam_changes_sup.html +couchbeam_doc.html +couchbeam_ejson.html +couchbeam_httpc.html +couchbeam_sup.html +couchbeam_util.html +couchbeam_uuids.html +couchbeam_view.html +couchbeam_view_stream.html +couchbeam_view_sup.html +dist/html-DPJLHKSM.js +dist/html-erlang-DQDXQC7W.css +dist/lato-latin-400-normal-W7754I4D.woff2 +dist/lato-latin-700-normal-2XVSBPG4.woff2 +dist/lato-latin-ext-400-normal-N27NCBWW.woff2 +dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 +dist/remixicon-QPNJX265.woff2 +dist/search_data-37149571.js +dist/sidebar_items-A03F7C15.js +gen_changes.html +index.html +json_stream_parse.html +license.html +news.html +notice.html +readme.html +search.html diff --git a/site/404.html b/site/404.html new file mode 100644 index 00000000..f07fba1b --- /dev/null +++ b/site/404.html @@ -0,0 +1,123 @@ + + + + + + + + + + + + + 404 — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + +

+ Page not found +

+ +

Sorry, but the page you were trying to get to, does not exist. You +may want to try searching this site using the sidebar + + or using our API Reference page + +to find what you were looking for.

+ +
+
+
+ + + diff --git a/site/api-reference.html b/site/api-reference.html new file mode 100644 index 00000000..eef585af --- /dev/null +++ b/site/api-reference.html @@ -0,0 +1,254 @@ + + + + + + + + + + + API Reference — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + +
+
+

API Reference couchbeam v#2.0.0

+ + + + View Source + + +
+ +
+

Modules

+
+
+
+ couchbeam + +
+ +
+
+ + +
+
+ + +

This module contains utilities to manage attachments

+ +
+
+ + +
+ + +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+ + +
+
+
+ gen_changes + +
+ +

gen_changes CouchDB continuous changes consumer behavior This behaviour allows you to create easily a server that consume Couchdb continuous changes

+ +
+
+ + +
+ +
+
+ + +
+ +
+
+
+ + + diff --git a/site/couchbeam.epub b/site/couchbeam.epub new file mode 100644 index 0000000000000000000000000000000000000000..f7193fe454191ac0003e4623a1fcfc1e4ccb1f73 GIT binary patch literal 77049 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%0AgEyRia2M@}*a>&AAp1PPTpgy+H zvH5OkUJ9BGH6&HSPNh+;aC7sp-q?@IV|q0U?8%@W;P3(kOd4y|$zbqVLq#u=nkqHw zovZ-b!kW?9#S*A6a)b}STqgq@SKFtz4_o`IYH`z#dgvtJZQt=$&ByvKoeX>El;&j@ zZ%j$YkuKiSDV0e;C7%DqiJ=fD#*{642IYILsQ<09EN+ppg-pLS^so?*s*W{ zkDRHUQ^=bWzsmXg{&MDh-7(-|sl>W5d8XUJYMi&&p^~4%4FPbaTE5yM2^NfYuD`gr zZN4QetXFsB3~Zy}HO1KX-5qETJeJaCIkywyndcMsR9MU(8fMb+L@Q5^zdoIeSFwQ_ zK{7v!nliC2e^}bYlNoaSyi(Sq`h=$julWynpCpdLq#QO%j1mKkT(S!M&jZ20homxgN#x%B4p3x|Bm70(A z9FrZub!)mWoS|EMX3EW@^B zuxQQo8!?Cn;c5V~h&35_O#ofN$?{rztMF3 zu~w?#rVUZ{D>fWci~+r3aHAgl`)od)Y(3?*76?@44sOpyoCHjspJ7Tix&a~IEQ}oM z!bdA(__GM1E^tjCK1Y&wHnm^UL)*w7hZCj9d>1^B3Nu>}6A2u#aRmy-L({%d>WgGh zU+ZP00yOL8rh>?EPIB$wS)PDMhDElvKr-kL+s%*s-?LADTA#iC9xr=DNm=#cBl@qi zbiD?Q7ydMA8*v>)hSpZ=?@9&~`TaB}u;9o?a@iDb18^3b>0Y;);E;!IlhcYx7jY15 z60Q9{9(92Y830X_lP7Q!uG%NK;Z^v?at7i)d&~7hi}QHFV^%R#FDFUDhFngl@Qrl8 zS}44Q#Wo5{P>6A+Z<<}xBJV+N^tM2=o+^2^ck(05#+2Z>aQ(osKe2hLPxkPD+B=i= zrVzS^il^NjjpQ{*pV3DB96DrgmFxP28lIAuq5k1 znLWJ>&f`{=*F|~obbo_h!m*Aoc4B(#_26HyJ04;E_ds9R9Si#Z9ku_Tl((a!slk7M z-dR)mU(r#BAfeUcl!2=Iss>E8Jd-K|oEHPx@0PZ);@){X7`-2_@WSE=I9!f9?4~h+ zVrY}$hd0+h;J<7V_wVzMp^@Yav&<%NXCUj63fY0|45X*XjH%;q%hh!AehxA+GQ;8d z-3djR@(h@Ir1T}5YDG^}LU*bOff9BuY2h&9?b3&SLz25d7~oL3wz4+x1!J-(B#Nd+ z0qku0mpCGM8q8~X)IkQgBm}v$av8TOL4WDARbL|xYGCWJ zoiZ5mYgp|QSFQxVepk5 zut&*P{HXyL<)PJKYRanPJtM?j483xlmx>4@*4#3Q*TphH!=x4NF1bC9E8(cP>)T?> zFrx!gu$8rAmm(1!K38RGPTJa<3ARxKXXvb;Sobl;DUr(`2J2LA2~61FCJ(Z)F~kEA z1UU@Rs-I=ii%*+Jt59EbCoCF9HNVi$uB=RMF$!^@4=K*hh{}j&WZ}lv3k%B;ES%#f zg$(u$X{aij5$88G)PC0DT})=05Z-RW`<+AD*R6X0f`S`tFeW1Fuh%nl%_?n5U)Nc1 z%|;V3mG8YzbaxGIg5b4R{(h$46E^BOvucFS;`&+xd4u$u&R&-lt8==j8OUO{A)|K7 z*$7d%At>s{m$*)!q;QBBw%GtHirR&>NDVW zB)KD5dC^@VjfG_qBhhM;g=@_G9hcSn4D<|G7L8i9aT#1l zxZBU5Tq*~&^%sB-i`t|ixH_wOt_W(O7T_mWNE-UjkaFsZP+h}l+P0WN7lP5$gfgf| zebO$IcqT5Js~OToC0cCl-y^BEu`YFH!s?AY>SQ|yR?Bd>jWcu7fmj2*P(?#O`Ft$k zlB3py@@U<^7cdfAH4x>}ADT+)VVcI=R0;G8#~m=JyI&*6fiJ@==Jo=r!YAyB}z+f4Q$>-^{3WiH6$?xsfm!(lo3GQq}pQ$GfR z()Sd@6#6bNdD^8{U@;4rfCl`t*{`jdi=V;4Kn9NRYD`_u`E2mVB!rmU8Jbajf@~fX zd1z5wwTf^W%b!||K_{T}0sKZN7c-vKKa)3QPBL$*n0HS8StD1O@Bs};GI%hVb!KHv zwlfF!-Ot0vFoD_O{SL~%Sw*khNDpW3KFk#CZ}WRMm~Ni(jrVr(!V)?;G0>w`SF6D0 z_rtlqIt^1z^cFjQ36;_(1UEjSycBFd;#Rd4c_6_OF4Hc8L8#D`D$$@W+KgAZFxt-B zZRnS17(z??0!a&61Kr<)n}2(>eCD|ylg-hJt8O6jQB#zj?k{GjDUv45pmjZVKdPOsnU@1&Pz_mSQKXF5T$T4R}+m* zgiU+*3LHfd<5(efavLUCBBi;R=D5T^^7CoMjQap86m;%XNel@<{n~vnWfX}DBh&Bi z!;~-x6ns!}lWFGpcpOwDBVwtL;l*++6o-;(B)Mt_vW0IEX&6`m@pfm~^O}abz-oe) z_GS}ud zL#SnD=|94svzU|`b7U^5R5a%+p&m>(E`^1*ghf@rLi}mW$zb0Dj2Kb6-Xfyy8Cao_U(wBD6n}81lS}sn!7TXsbch|4d9}RFPH|9OVDckR`H-$Q`J!|mJpvqVt zJY111oPD32hu&T@Iv$IDuzai1LMf{*06I*9fY~pQ8=^H&NwO|ycs)={QDe$a9C+P7 zotUhLTgtZ^fTu8KZhn;8_MQUv$EV%=Eg$wX@-gd3PP)^_K_ru5Mal2y4=lD!zNhT! zL_&3HqgPMLi$2^+Qivpo<~CkU4;!41^-=RS?9U!!qS5?ZY~LpS`ajCn0Z5JB)8m=l z*)Zc$%@4L6Ll!qM|2O{KW}!@X2LJUxHURp!@oz^5Q;Yw9{Cn?9k^B$Nue(@Vv8zV! zD@fPHIz5p)9c7IyCz9_+Gjk>9l+y#weM`_dx zB*cGW?bi3sfgBix9?QZ-Jzh8=@8$KmsB*xGk==t2k`j@2paUNeL!1ln#RT_H7NGzFg11~M?E-~Rf!d}bf`sD?J9^FzE`O%MnZdg!qvpi^7Q4GYUzU%R5 z$)S7C$1TIgPPGswTj4QAQ5q07Qt3MQpl`geb*gq#n17(e3UoMOCa6?4@A zdq~Jl$z9@V&~ASD_dnmB(Im7eCw>=IDRY`;5im$X7Z!&;r&4hMfix&FCna zJ^2HI<+*Celas)5C9HcY8O4?zX^!!PW(C<%rAp@8USCOm))C*S(qM#1msI*DMQ~HS zo6SB_XYb{RxNX{x8~LON3fRlsw;+?sn!xUG4ycF~XGcdxN5^0%Ao%{l_$$GoqXLN; zrgXEduHrO=Bx%|`ZXZ}Lh(r_yZF~C~n=3=cI<~8Yy{E;>ozgZKsk!a1A>b1=^OS{p zpvKF6Xd2iSC>-cM%zp;S7bH|bUoa51itHspu}1Jo5~oN?eQxQuQRj@$VA#RoS@=L?u~YeN&W`9!n&@r!=1gD<;hP$?1!hut?DNr*D$zH5|2Xzs;zDSd zSYY7_3OfGSV#U4j{pVMKv`D9)<4Xjl%2F36{?=T3x3O1yV@RYwaQvjGcIXRzs`gWL z@N^jQm8;fh)sJ#P2PPcPNBDnsE3Z#FS>xDcwDNA-I(Ym^n+1i`WDpUrFn}MS4z>(v z7@dF}OFD3UO~}he#0@>wd?ZGj02j?dd(3F(-@(KDxb0DMrmfqU4TKX)2T3GYSSuaQ zqtBb-FHl@n+^N4(kxcFqF?_vv)KSL?cRN~j1QJtAvaq;>%v!O`DMs>?Z~Lj$iVc)u z^V(;1vi=L(E>5>8M^vdo<9v9iHQqZz44FW{$K#ecqosX}IJ;SXxtjAhZF+G%*c2Mpjbt zg3ZFgqMTH66^kXhXrJ-dAkRa;dCA_|JC`A}RPGV#UP0?Vd$EbR^NacQ6)1=2w~S3y z{XXiwb8fsB1mb7wR2oh6>&aVM*YRc|I4|O8Yuc(>A#k2dsuHMQ4FX~=x?B_ouVmhX zGrYpiQq#=~!i?h3^>zv)8l1Ty*`ad6QL%z5hs1IA%zK1c7X6T@#fy|bd&F{pnj0*G zHAmjpNbs19YP$r17d)xe6oSa>vXf_>Q}>REiM zs-XgdFRha_guA4*&TehNqST+1iVd(qbbS(npVM`Kk5y; zZXJ2~R@Eo-sTF6q!5fq6=-LQzw!s~ZO#Q86)sR=i-VSV=kTn^nMVfWiZ+%-{RG2$G ziAYby#{;gLQm)>N^{*dvPTWMdy1PFaf!@i_wf_l`CCPoQh7kuhUnxY6Vd5car_M7F z_e>vktxF#sD9?Gyq=))Isuz}cSAp+WGcCXQIXSlUP|6SA0HIBU8Gn2jatHqu2@rR( z1*SK02W!q+kp3PJVHb@ihKa=o_rX*ki;*T1BN4EoBduBIVMN&UmI0I-Q6Qf$O|jjS zK@26^Yf5kELAoN)qz%z&VN@(=wy;Z9>-6f6_cgEZ*RinG3#o9Wu`gw1tj zZYpTBwOgl3A>k09gh{O9;|T`sQFNpnVeX=sKWv-02Sa1uPhVdwGmR#o@@B2-JflSD zX4@;o0!b9gP=fP~vT?#?IyRhLUtTjxb1rbQoRA&LhE-fP0HbiOxj0XP_&gjpODc2 zaUMh}+v1sfm0@~$7*-}%fsx&RFFn%fs!hD{wi!knyX)oswYHn{ z1YASpxA$aY8q*wkFSxh!HniX6lLPbG$HkB>mUYTvXEG-kpgtoy?DAaJ5_ol72HFH8DDC5cSV=UogK`=sbf^kh_FmD*mX6Mwkq{?Jhyv)a1Tv? zKK8ScyLd$`^;>`+mvX8Hyl3aT#-NwBK+5}`j@ySMV^d<=O6F7n&1jZ6cX!XWp=iBZ z16LRVE<|A}SS3pwny$2^i{P@#^MmCC2~lsXbmw?WrPcOHK{+LpREFm}+o#iwa{IGx z`?A0tpYI3yUk{JHf0YslMV3E1|lp9e{h~V zcUB|gSFOyl@Cf@nWJB40=ubX9vN4FO$R&Z+JAQ)3jLJLzvq- z0!*Ow!J7yAiHFK*#x!FrSW}ynDBC3&<4Hex47jDC!)LV+-Zt5XpI|&rniYJD_W{yw zYXDHAq2h=@vuVOU<8qQd5G_z;-%{;CLging7jWd1-O&~7@#xeRZ_^QU@})&BS8JyV zEJ5lVjHy|M$sOZiTXzmDoXwZ1Fgjtn(B}Zp^xOe8Z*aL>Tc~>+w2fXa2e>|KSTu_t zV8rkSs7~rW!BQtGvw`UYPo!7Qv->^!IL-@1U8nXM2~$DAyx!8&GjNW6vaZqj0o+94 z0bvBm7mdnU+k3QzZd}uQSz)2WcCv&3-gCmQ_4LZN_K=CQyjh{&gx*stg--Cz3lmx- zOL+VT|IpML>mG6hwNgVoJixRzcY7wfxMUP>k4fUHiz9#!ryZ6R%M>{@MWg^A-%@eG&1PMFpuM`VI*WWS zjO~zV@?;?UDR63n*FouBXUD4ts9o^Z7sd19upjIImM>KzSLcyo=}U|#nq(^bbJiO% zM?2NV^GFw~WRlWWm%K8RygYJu&zGJyLWe$?E7?oOed;ruy4`9p!)R%Imq$NZWpeGd z;rs$qa6>+S)j{6Ub<=yEtgm{Ct)L4nIi5YthJN?vE`M1~vBXPUi(;dthNZlB=f_qr zy=@@Babp#zy1#keq`&JJt@gf!ieO2Ot9i-KLo`4BO&E>aa2_F{E*W2F#oDht?mNa-tH`ycl(9%Rj_|`H_r;2pPn)5SZ~wW%k#tM zM&}3dGE0s-6_LA7qS6MvB?IFb{&7AEYf_r}@gF#FRQe9UHY_%(ID?!Hcbz{OA? zZ^&|uMB;AZC4DrypLJm<=BYD~lPt*6_j4U1Je&~K@oC^u>j3?9$y6+McP{h6WrmA6 zq-825$Du_uPuGdjrqF;uPoRGeU17KZ@?Pfo{rO=dY5!X8Zq?(IDVE!- zQnQ;7l%o;QI=G}}_TxF72fulFzSb(}&w8*yoX;Vz$j^DN+Lij9-C7*w>Z;qgVfH40}efmG7u1tQpCotL{zuXgsKYldg_*w$&|5$!E2@+4` z=aQ1%VGa1AuF#pkZt4$8r&KZWcNw<6-6AgPD5OQV3b;MK zgZowA9V`_DGjWqQ9!3QZYX~+Q(EE+8ikJ*zx(ezWAj6vuX_vWrS9#|_P9A75l8_(Ge+}J%|6NcLBSo)l$D_Fl6 z%N)~^kYk#Qmc0ZPIV^d#EOsc&4w)dx2L zTu43dNnc(>vcz@9uPjC0SS!<|Y4&`JXsh*RQ2bxG6>f#izi=x7|ASjW|1aFiyzduo zB|7ktPF+@$%k0&0D&W)$eimrf<`M-^*a_lbBB#FQ1Fdl9Y$Dq?Sm&`CTI=<&t0TIi6_Sh=7Dw$EVKe{R{~z2+>vKp& z0h%R`y#L)_xRnJRhu-ydbl_O!7Yuiu&@wO-KgUM>o1}Fu4!-y@HgC}yJ6g*!sY;8$ zFUiEO={N}z{M`1$sX9f9ds>O|=;`QDp@k3l3L`R};GPvZAndW)EkhpC%i1k-hg__5 zxc(0i%j6LbhQ5pel!%`n%)UIKKTQ$tKg4(`nX=Sbq}%QvTJUHy5!a8TKeF!z9-o(? zZ7hC%s{0R4{_^)-$=<;&j3|CJuyOrpz2N%4^QREyu!Z(7vlubczh7#ZI5^no|NjS2 zXDZqXUxgK~$-=4NLHx@bquL9L#?dE~ zdjtf8>G%Tg6qBSKcTOMTz${O5;9FxMSaG=k2|E)F$*??uO6NZ+1Ugw5Z+=_s^l6?V z#Ncv1&G>ep5**iB0)N(W@)$`3`bNm1pe6>?>_E9?y?_&attwYWb`f>0U;3N$i>+Rdwz$Bko&>)2Ci;VPO0T5W~4 zh%pSW#sxkH1;&vUzFE{hAC@_8CBTD!_qUu!hZU(rKupJuNwfY9STM0+vo5M(f-Z01 zJa2Ukwv>M&Wf8s24<|Cw?Is?$*aHQOG<75=biRT_mVC{tIsvdEru#{4ZLHia;L>i5>N6dpYdwIo!dY!sIa&SQz5|&1j$uK2IXhaad4cpSn zQ^%w4!Gfnu;FmlIn$)geCvD4j0$txF})-m5ux!zAmtO~&NDTOu&T0>SbXM_Va z$^5W`ev$8$@EQ`6a(L51tbP*t@Nx0GhV zN0yH!cyqzHGEpKUDA#M4&*#+hRnUc68dvWWx4a^je5O)f8!m;b1PI13Q4%ROl9NlS z23gz&4Cso_Vib>xXT=4;QKpERV#f9-TJ_AP&wl81vQqzoi&E&RH-{1rHT3-u9)?Y; zjS(H6YB8D!>hD9&n2{%5Y1nfbU0ASeabc=Z(f|~bHD8Y{v=C>V-~eMI6(_(*SEz5G zgH;IY6@v!kD>g~y<_iMK!SUf&>AGwn6$x(V`%7Nx8yam)1Pf{Ooc*o$(Xc!{UtakjWNtVh)K&>QFf?1TIdfBWPVNWaDYgmwv zG40sEI)_a9sC2V4wQ=-PUjN)LDXnc0bzWZIkU6a}`r(S_Rc}9bcwSbzyC~}1 z@0&S~dX9g1k#PjhKe>!_>iv@Iru`W>=@;SE>$$`C_q=6adHsvshUj&vt(%-k$ihNX z1raB*($`DMAoZ==d_U6sEP5sRyl$s6Gu@BWL0>JJJZF!f<;fkdvvpIPLs=GqsSIvH zURgfeMIb#@_oV$-+0CEYzW6SM@Aa79Ewq;PlH`eLsEwY6v>`>LZAeuBCam1NBH{t8 zX2%}Kw2-Qmi~3)yx96p$G{{~k8VS*^m!}fc8M@G|2nwn5pAO4n;j6X)0L-$^pA#|? z!SbF({1EsiWf5cFjwL{(3#dy8bXXi@%{CHf^3IAjmIhCIf>_o!3)#hLRu!(^@>lE<4V0^In<6|7rRL${0HoYpu1u+!*KiF>A^>uV z>C6(fCHnh(0qV&NWc!=`4&ZQD%{6(7)8|xhXn2>W&`!$35SYli*a-(lEv#39RWLEY z3we+tI<{c0JoWtGfIy{xV2v6I#4_&CFEvC0oH-38AbQ@xospMd;(__rWP*q)qJp&0 zI5mdS$|03ggcVI%P>z>oKi!9=g&}^wO5jlxsTnD%iCD*;Q3>Tkb5cqQg2%^E5@v=q zAJ$n{%prnH?LiHxaKN!d4Tro<^YSybrGa8Ha{UO^=mIC~M#lIq4fC3xv=!cd^Uh|_ z)z{7iF4QCJrZsa9{n|$SQg;J!Ji1o1xXI9?$>IzI#}k4s93xv@J#1?6z{bxru71-) z_TJ)!q4=ds$I4{ia5W?m@qvyPKDlAlW;3Jhun;f04bAh{7B|Oce0BQv_Do&>6D(V& zU*?~7MhDL4AXrBoWt~$N+e7UcvWCFXS@?si0<^~(J!!snd(MW3$~wJ=l$lM&)ZL~Y zmKk-60Mld-rz!(se$wo5lyxobZ2#(exe6sjB+4n?r=g7WH7)Fw9X7mm{}pCh$!S`n zR5;InF}i`B2oouM-3UCX{{4->@GrUBe{v)EE9QdX@kK~mO1u-u*(EmD8~VKz14OmL z!XE}FEC(7Vq&`M0k6*k5{;)e3Y9)Qvtxm(GmjQ<5B zdiZt=bjz)82da=CLLgYXJeHaMq#-%|7a}bM8`~r-0Mlp|i5S-Bpd8{X6OMsc7?Y+y zTb!Xf8vOkOq7Me@=Q&~?C|UMBtX&TM-#j8Bm6Bj*c;FIn)L)oT`dR~~LN=bF7bM1A zAmiv)^jEK*eEbtN$T8b#VOw$ZgjGA=%dhoYB-p*eRZWpx&JMK$@#t);<9SH8Q2i~LEGTlxyLU?t)241epxO!%!?GQu-*XOLCTjDZW1!tDEUtDlsH z35cv0tyC-Ek5Q51G12%NN2HTZHr+HW`8$~wH6T84R8duNBZDHgh62`F6EcxR?C7Wd zF*r9!5vU_+SPO;};vP<<{gDjz+Ku z;R{CefbocOn4HrO`Cl+1YtR8*mE@I{lQ6NuveMIz%hDMxYEUf;IqP$qr4rR-Q6UQj zr*qq-7FUN#wii~%Mclx0b;_?dpwxQ(pzf)X(B7)z`5D{129I()3q>-|5Nn2HI000+j>APMmSl)xaLPjD?yi+d-0R6PlGQb%-gvwsLBbQgY(B*M3TV56;*-Sb2~@9tHI zUB$^^cjDV5lnb(7>Hd?RD?#fgmkFZ#%a!FA!UZGm*p62IXlOHybsCFdd7{GX=pOG6x zFa0YFizXx|OmwK&!2vyy&CA0db1zhQ+cv1Z#XAc9xT3m#s78d zYc8r(&$pz-P``Wdc_?Yh5kJbkZJ8E#6;d2hKI+QRM^Do98e_iPLyxhZdb zE|qewamK+RbfZ4??f)|{_!$m8|X#l~_{4_oQ{2q)1T zDOuRW!4cWW*N9{Rti$$kn!kSaJFKb>=XxakMBNsiIjN;fiP8u)SvYVCanb8u9@?a5 zqF=uM2voTVqw0fG?tT>q%g`&j*c_NvW67#Y80ByojSXA`l&JzmS??WU934dH2H$>{ znU|>~AH0BFPa-lpg8mieEv&65im0hAL`eW(kw2lSmm3bbyk$)1w*y3lXeY8g#hi1P z*?~%l!%1C&G&9&h5N5ahFdz!d^GamMbg!w(Ps8E6eB+WL5)mD4C#VqI_ltHG_ zLXjiNtQ>~f#?}cAT#HL? zf~>rv>PGP!G2i3RDhT7PsIOS-nW*|BSuz64ZK@|PIWXju5`cvF;vo;T z%5QirMD?*0dKS08#%cjOoQ9y%FtH2p?NpBA%P*qqhuLv%)!d3KmMRzza1ruj2`ACf zcshY^S_SZ70kV^p1G5p8ZGVi(0kox~Y#oGhnPv&BU(f_#`;)Q@-wk=)f4|*ea?r2B z^4R7&ZL}uMmADxTAbC(%BMGU{4&Oao;y8e0EVQbGKGoKcPFa zwmMKcV^^wiKU2mgsn~bEjHdm^2H2cjCQn#5mUWJ$iyzQ%_`agNM|2LwmyO@qbHaTLp zqMYDVR|2N)bSjI66Qx(@FGLri9G3XWO_I*w6wShMK;E-IqC`fkx>|LGPg~p`1+Ca2cnB${AqVH$EytU%;|TSIb#= z2#?i}Y`@B7+E#-4&TCGx4zk%*ELIz{`Xm4cUs~;M;NNx?`wU4AgM;WxIss>7$Y9O0 zcBgS&tkV)R6|UdBfq0$m5lJk`q>a)+8zOmYx92J(L8>^wOzKVEHU+JgnKDmKyXdme z?g>P<4M5c!%QFaFZ_|`xuUO0(A&Po!S~vNzcuCmOL%cb7DYDz-Nkvml_;}qq&0evI zWzZ41DE(p1yO^1}mZI3hT3zXsuQUat&6XH=Bn@SdrOU0a3g%Fy5PM>h_5mD9wnrm) z&)f354X&^}g9a4d#A-kuQ%j{bq>7q|U5A)$5rE1t7>~?&$Vt+Kwe6EsPEdjP8Z1573d%#+Sg&S$O(!6+_9Z)StQpI8!w6Kr{!6I$=k z4d2NAq*lB#(EnnkOn>&NDoRoy(p7NM$-8ejV+ZPH6`!9AR0jQ5M85xEHArH3s9=vp zW|rKW=Z=w(vLX0`&_q)ggF$wXIdzrLcW#%-rk)HpP@M;#{SAK8*zKU`O9ltEYqvD^ zFScLraM=5FJ@70SrW`lhvd_AAORFW9CJxWud?%_X6i5#3kP$*=6o8n1`&-PQ=uelz zgVym+n4~Jo*+Ksn4xH#4^J`NXf^n5%=g56+(J?i!f>- z@gs7Yogh7n>ry9rqJ24ju}Z2~aqWOx`NapK#^kVVG%$%|x!LtNkCLwY%1WSr&i1ep zubgn3M#KVgC^i`ZMrMFsCwaJ%z}B~3Qb%CLW&{+Q_KX<{8~8d=)0#9y(O|H9#CY$b zFJosuI%z&1M+ODyfX>yRYvy_$r4OvcQ^{~MZeBf!b+EO^T3{(}y^V#V>qfN+ms=4K zCq3 zL*~E{kp(P6P^sdps@R+6PECpFd}_|#0RfDZ6foNx{zz6xK^s7>|+A}?_8vS{4v?`Vy4;bp_Zy_W&O|Y=q%}PBG{kH4^%%p@jpXj zx%}$A3&lseY+c`4`76Om!f6VaDWc-mvsynr0&|FGolfVRzMjDLLFCa)d)yt6TZrs%(rK=t{U zQ<{o)rn=B86qW&6mR@2KaN?DsC!GZ2&p$4ITbbb3Y7FP0!>1w*gEASR?CW5nBW*vE z*MPV%10sIC1ck0C)#J`JwQ$n@+0U|V*{G>M(fjEsC28}_Lda1|oj}>}wN4(DLqRIw z2nCZ62+M)c5Go^V*a}!G{GMWIL$q-++qQr@i8bwW$RWneuiWG==4#J)7lj8(+Ei=L z5stow#!%{^o1l);c+S~d7_$ucDO6@O18Jm-B92N@Dgtk6dy2DBq=ImR!d5clSzyEr zR@^jhQczMR=Dm%aEzj9`x_M`P#9rPsq=|+>>4H_Z!-)I~ew6H8Ff=sq6(K#)wZK4M zN~rEuA2>(j{tO)+<|eYlq2ca0K$|K4r-dH#BFe;Y)p~z=s++(A%`Bqm>2tt>YB+FE z0tdFxU|dx4z9LWfb33k2Hic?ojH+Ui651qct6#Up;If~et>6c^uP;zq^$e1C;;#20 zPc5HI`WuDsBGz-jRy&vPBe#oZV{f-av%$--z_#dM@1#%0If6Ek$HUHm>>c46FS2Wx^`=ME^&1Py-eT4`1vJ=Wn#IF3Dd5%U?=@ zXKElmPb_k`Y^N|SkS#m(#Rec_l*{1u{Y&`ef)Q=*Yc}X4nd&4N>C(hQzE+t^mklBD zzCbX$9LT6st(sH|DR>qFGCiDbRewdQ_3<9^YiD=R zK7L7_BqivFkKO8Q>uI#yLm^2S_`E$}hOCY5t2|}$^kNI4AMW}2wv)we)2j@0z;{xDD z=G;=}hD^s-eD>t9nZfmL>A;r#l)#z}2zRPwH zOE(snB!HU4eqFdo;35+2l7wslf1C{or^7C(# zulG2|tqVPJz>+(KAuD$wsDYg)w<+ksk4Q2Z*K5PMJ9`X(VSzX9K_#ekt{SBY3AIW` z)$i9dqz5u?s)^zH0S17uJ>5NaOV1E4Yr+pwyT<+QZ=dfmxRlgT9HU!8MlF! z+6!E(qA|uwltzs|#P`MCrav`c@m+Vw=UtH(A~DkCOrUm%&O>)HT?t7mUq@3Ds}089 zK%zr-7>7cVQq;*`i&xK+HQ<6e0qJOC`r(W_=ybsUj9FKzmOFp;LRwhy>}DYs_ISp z$=$mdSr~NmKM?C%c4yJR^Fz3xwDiQXC_iz40G*b%%&kAX(W?q*UfllUTAqWN!uN z;X2s;421i1uLLc>+WT4jdbo$dpU*f((NR-tNk2P(Fy`QBGsgVqG3gf2!XrDkN+gT} zE)3T&CL%PdQ8;P=-}_hl$l1AO8jXfuWFI`id?!SxSpVZ0;1Gb5YeyCdMRKT|Ao|-d9_z ziHfw_yQ*0@;JLl6k!im-wu%Imh5;yo;ms=u0jXup*ezu34fY&!xkaMr8dNn9qSkJ0 zc)#r}O5yzvo$LheG+bx3iS7>;V|3_3R+lWb5@5`xg^ca#4$~uLKK>Vl?`A%4lZEU%jP}dLVoB7sS`nxyT%lgQpr!0NSu--u4$wch=AT-PLFe^ zh|DH|e+uXgQ+9Mo&^8-oF*h)LZ>o#m*yxbMY)KZGM96t=(WBU7@oD|b>;m?W+2tE{ z6IJs+W|vB|zs)X;+bh>!W*1K0cbjT2+C5cW(W_a%R`ZwH1qS2G>{7J&m)XS| z)h;-;_8+s$>|bUVvwzGkee~ABdNh?>UuKtxzs)W~$UHI>AG=DIzp7+0P*-IU;~iMu>}S?js&REX@?j43J4`sqL%IOD>m!0`wCVE4 zcg9^6@6KL9E>9EfmaS=FrAF&Tn^WUi{n8vBLw^!Gq!SxOtL4z#WG&HqRk4VncsnZi z_;=ek9h~yQ<;UuD@(hYoVaYs=$U*(-i+o!yDv#{Uwr`_L;OK-h>`fuUt(sDSbNW%@ zI-oiXL(4$Fq6UTfHRD#5X%HmX0bL1YYjdnl7Ic>W{}VNMm&`UTmd7ffsRs#ruO#fsPh2IO4XNIO@JCADFeyWD14qzZ$w?U-Q4GPCRkB8kFVo zbTsL|?JmxPuTMCaV&I+Y?oYR~iLH%)tuEld-GbrXh7ChW##2@xsZpbS?93hNMMzgv zR7~Y&dj}kG_FC|I`w2{O!+p6F2rIQt_6E!nLsJJ#Z5ST)5u|W zP+-L8KoiUkGzI^x{V%&qVM@gKSA3Y{PG-y72$DPOJ(>?%wtpsO+(w$zMj8W2#TJ+a zLBa2Mc!PK23WGcBZC1joErmJvj4vy}|3H3EE?Wfv2|7$FTVg0;00{E=GAgioL&Za5 zmhupWNwjr-HnqEb?(f7}H=9K>qSeXrhcu1bJv>*o-d-=4e^xq4{GrUT(fQ$Lh5&{n zlYl=_H3w{$;udGBpOw!%!41r83VweY{!wxy_d7=wg4V{HxH>0I6|-i{o;sl_gMJ!5 zFZqtKoCy|3lqEmcW-Vhnv4#Wok_u^_T0jsFYs9Q8HGZr{OmX6PGTT0j3O{RG`i+S*xH?;)!-L z0cz9Jc%!8Rv7(Z()c>99M6#4P2{2n#mo_)1Flt$MBneY4zy7PUq=!ZowK#nvVWT29 zGcJraQq_CmH!e&_JFI9yy^C=wJiH=+qzF~pKVyLrtp28Lt@>}-OL_=-uqk1YLU~E7 zCU)9o8`!Vnz|$4Zqt_PT`N$%NUyaisg{I&0FTNkDCI8P-BIN^27&B6KewkpMJ6kF} zyt1`2*V(u*{IqzWl4<(hiefmVV)QfH0Qka{V#n!$+qOZ~i09Z8Z)naX!+rfS{Brep zdLkJY)U`~iDhO9GT|1WRe6SLzQF-3E&#IG(UFFHj#ONV#>Uw|P+|Q)YeibQWz2Z_Q zyZL8r3tv-)RtKQ2!hFnG_6sop z-4}V67kRTIW5-(YuJT<@owd^k&i7&c%h%0Oir=^wi~q#Ea7T;$Y9C=kl2E_e$I}CJ zZ%8jLi~yZpw_aLg{6$BfPPExJJS}8+nA}M&4!tX_*ac=I31+{XFNR~NtqKZ?n?BzZ zm$-=+Wtb>7(?cfSGPRFi(^EH6u4%F7Ewsg`(QU3ij#Y&%yT|6?vy;<(Wa+bLSc?%? z_;T!wgt6b0b>@Dhjo8osqupRJkx$P0Wr1E<0RZ6q{}-|U4dM0w7EP535;nCav-lsr zz;E?(GOGi@iYTBb4{vFkFXC6Q4>0=i{!OR){WNVdmw6JncYi@DOo&4Z0LAJ?T*1ZjCLZraREH?e($dnikqLgPCBw8>@Ho3a6`iPd zzB9tHM(#^>LWx#K)XuRnI|T6*=$OGil6Huk)89eA3vS3#BL4tRJdnFW0Z`~zmZO5| z#}1hZ-58l2yrhx;@IOIoxo(PG7xF$duoPnd9RrAgAVahy$e-WOusb{+oK6qxf0F;0 z{%~K%YUpyM5CM#nZv0Le<19q~-Gt8jpHN=(ZHFqUDM^NE zcv{cevoynODFwXIDc#zzc{w8&?z2AuAePv62xbInCF=l!c_b$h`qn2PX!KdD_To~| zV}9iKE4RAXo$si37OrQBW-NUwHmc|-@vFi$A&p7ike2q^V5UiqVwGg>3J?Q#U0vH? zx&~8*10j-9jXilYl8@Cj4L{%*I9H_UMEz-LH6iPhH@PC6!yDRAmjtgz6kqsf;Qd<; zib>@(Lh5ekh@cZ2`JjFHg%Wti`z^rq$R-z6i43K6mrd?VmPa+hU(yiR2sotxOe)9l zmU`NLTImYb3**6AdSF2y(s%ZxRb})t!Mb7_n=;M1=pkFr8dSv{C3Oo93($GyO`q(8 z$JKGS{H$g{5j(>z0+R|SSE8wSoTAFBQG}#~M=wZb=*LMUxdofSq*Q(~367NGRibmB*evr1@H(t1{~LM<$oFy{v}TVXOwsE04qt;MjDz=Rsv@cAY1i zDnbdt7uyy|=kM2;PYTvL^vgd*1{K*UQ;9Q{<67-Tl&VbqsbZa7?f*PreY|xV+7~mM z-;QU!e8eT+3@fth%NBXui|2`$B?)J<_6Fr zWm5AIKV4gqX+Gu}yyV~E{xhAq`tNj>*;;%hJ@H=E-KR0Q`Ut-V485|iJWX7tct%CeLR#+C4Ey0Ak_GI`J zjXzQm)*--+58x!0PGpQ2h?BkinS8M-D#Xn~2nd?%kf?~6^0Jax5YdDKrzt5IW}dLy z8h6-Nx?0G85xnWKjsx8lh+``p5W?lmCETG2jy_~5_H?g!aV-#{DH`FUPgVr!NmpVl zQJ(wfdy=x@u@Tfu&h(SS8`3mwSv|lH;*J&s5mwet27cd@S!{2P-R6Q9)WFY{3r5AD zi>sku6PjCVRGqFnjys0q+RtnQME8VgmUk#`p+#&>P-H$)Ges<$M|8}SOl%(xK1QR^ z`9{=ompwoQNWDOTHl^vi@9p}Q{KENdRs@^3Ct4LHVEvz!BG^dl!2$(J2xvFYgm4CH zVp*;7)~!lmpQs_T{Ex-_AwC~2AlG?4kSB3F77^*c`B6O~Q4BAiHu_*+UxK4>#E1IL zE3gTh-%@RfJ%;-LSNN&g=yQV;>CTuuh!r5$xyBnv8C$J*r6#>+0fSo1Qs#0OHV0$6 zc|H+5Izx9#+rKB7-;SPtNcpsmQ{)F&to(@)5rfm}0YaskWW)3o@I~C37$kA|HIg%r(V$~{$%tD4 zS|Gdux`WCj^-e^lUI?%GP*tEG)GPpcLUD=u_4jd9G~)j@VjO1-2@B@LrGZtC`BJgd zRW9`L=T}SMUhEPI)zAGQtT_NKE}K~fuV)objFr6eMDPO1?6lEyLm);iF0Rf`5JB4C z)(PVImlr6-)nacpi)d%2*^%&h6O|I zHSq_|RZ!_GVSo>5!eNN&q0e%J5ZRAXJ3*ZQjO8%hUjAtxl1?I}pkU{lftV*))tscG z<#YOu{_>;K3y_KBaI|INVJxh8Okp!i>So%FJp;P*FdXJ(W^zT+E{_LSQGq^0ngWOI z>?Ni;vnhtuNEzA*;#LX`zh+|y{B4bI`27?!J6qpNX`7!Ug(ald_+J*N-F7j6jgBke zmJ@~FC0-MNs5YeDX9twtRxyBRZ5hD(a)+TTRBxNL8(9wiT{o>x-@CUnpJi}g)wBoA zV&pZ8{P9cawe>v(v1~24qANYlR*XiL>4zjux-C6e>8!4^*Pw{7VorD!>`CN?1E4ft zYxsPdVZbQG)|u`Q2AV^#?g+{;!6c!Btxiil@SJGq$)P~sT`{X^3#h&IO3PSq#PE>3sJ#UTvr=}h^9}d`hP~W8?|DC+mta4Ix zxh$reZPX1(dhhkXr#0FM*={#NDNGPG`J(e(vuWY$dG%Me!Q441438? z56Ymd60~Kx86HPrg$Xya$lX8JNA2p4)JH{luXm{f|CM$4D@^y&!?|iMxY=d-(kOS= z1&U&c)bRt>@1zHm|Eh2QgA`#e=TG>b2$~JjXKcVhojEuWF6PZ1=>HTr8DYZT0*6ra zcH6nAX*7yxaEzh`BWysvbKmZH6N7A=-Z@7prHzoynOHb)#GMf(yVH3{G|HFe9zs&i zS4b7az;v=CffJTyoruZxJ!RzW~QI!3sRKF_CAFxjR zILA>o6{z+#oZX@O7f*?&yu+g47+BBT@RC7!aG7{W5hL6{@&!~VLrtgVwx-a^@toC* z3;WPYh6oO+nQD)!CUKD_u7N>b4gm$8FbgXATEDVF*n+h7gnh%}pag^ln4tJKe?^>?Q3x@AQujEd?0xA0W$;>y^DjR6^O83FsK zR|$dLk{o3mK~kh>TYXuNf2smNM?C~3Er$g|>{0I>skNF>8A7R&eJ@n$Gd( z`4a=i$na)^#vsr(&ic9oaad0W@GeX}0= zCBN;=$12*V1wbnG%v5NUIQ~D~s-AVE?I5>8ToX zl1eS!sFfotR14ZbM^w!wkW)|t2?E`F2+$6Ya{dh%GCG-$o7$MP^wh8KUA0Q7t^g6i z2Ih0|iu#;cmEZ3@3 zvJ&yQU`O8zXlHVfR`+2neDq4jK$aO?rBnH5+nc=$5t zP<6)~Q9yZQi+2LAH0kGZCnr5=nKE4@Sil4!Rq6qK<#j34SyGSFI;c2X)ISt!ogDw) z2RQiNyGVtv!AQ=%t>qxqf=VTdJ1zw}W%u12YHV@&eOrsuI3Be%V&S{Pa6ZR`34^@0 z04^tBH9=AL+GFB{*F44Lyb!Zt^IvhMZK>%&gIIYcm4%Nz2Zz_V-=~*?4EQyH?(4+; zV&e5oOy9j~KtZvUqw3$Qdwn?*apSzRW;$jbRxjSM#i&DYW(P;>zJoPcNTv=UBAWs_ zSDOUwPMjH1vvn#vHCw1K7wm{D__R=QVS{H%Z@7G!Dnn8oR8FxRe^27cr72|0PqBed zDcZ_8?UyzgrYq1L?`_HGq3dmI%qSkIp{v*JV6=07wJFvMpPCu@An0)}8Q;cO?8d~N zTgvzb96GLd#mI-ZCOYpihJ4^e4H4ng^7SaE_sso8Kr2z7t9QZI_RRbanU+S(cW3t( zVlETrpB>jbZM@Ge>O;JD`tSW6)7HxwHxJIS#wY((MKI&i@==^F*8)%3lfUouz6+sm zhiHF?B)|!V_4lN_)U0mMMZ2Fd3VEHRb+TgYSH-GV`$xa{EUd+wy_2^v+&@xhG5dZ0 zYYm}WMaK4!6~6mJ6}pK({x@~e*5z>Im;5wW5UK~aUeHRIS6nX~M2O-u1k?3)%auf4 zeYmE+_6HN6Rm5?p%l$E=#S&46y5Rh1@pSV1=)xmGnzr!DDhE@AZGEd(kT#7WvMfAL zFNLI7<;Hoblzj6lGNF>3NySkeH}>s~m=xK$hmSJy<+`>IdMER3Sz@XdmY#1Yj`H2b zN<>S8S|0DOjfaB7V&L>^czRB3YzH^R>JdLJqCLp>El-kf=0GjD$!HommC_8<<1b5e zYwhq&J9p{*a?sK3==*OImtJz<#phq^FSmP9&2s|*m0k5Goos72d+xz;is&c#QMQRn z`-!Y>Pz>XrX94pX$f8!!#Y&`gtvjoo8wip~Q3$|YeoAd7gqfMXJWx%7wNfyFYW&(X z>iIs%dVtD2;S7{mCO!LfDAhe2m|_gQSIC^CK$gT6v0x?|#_YmV7mBtm$%eqr`YzF9 zD`;QW$aU(iMbpz+p#nQIvKGOTYsBCSQnb>zjLu5HV70-rQab z3A8J9_Q1N6mV%`mK%_pWbBm;vD@6CBwwQf94{HhNJlp{PA7m9-mtcA%hp7F?h8|5N z=GMIXetQ{GGm&~8ghjm>3fD=rUt2XdyRmQQW7{?(@xOfXbpFh(C=K+t5UC3U{NaVn_}u{+vdMDSujo>%(l$;#9j5Ih$I074&92rKdH! zieUFq=pd6K$1Fk-oP)qED4-&%F}dB}G1A=dNUNsxe2U6Q2Zv{*)}J|nD$|(*)QdLN zVOG0qAFohVjb1GT6+pviL?|t>n4}gH6xxs3Rh>J8e;p%>E?Va7=3-^W@2~b=3_aq} zJMTv|x1<*L`zDOt*u=-oL;fDZq-Z_l^Ib^`e__3pWl!0aUL=KWD~E`cGRwOPUR!bk zO9ZqPnj6(S?<%z|=a)CW&tf>epRpXExbQ=4>5)DweHDyZO$4L)9S3$ z?>CYjLj>|SlD^O9^ObNs$&k!ut4K2yKMeWajhol?Wh;K%)z-(?`}=%QQ|=<77(CqD z?=r%kCAfIy2_%2m0D(@{fZ+7(_38>*TNA@9m=yZ)4H*$u;Kv1ED^`(#z&R1-x5(sh z$Q;g}c@kTIDl!pJK+r0%F_njn;M3JB3IEkEG@YmVBga)%ZbCdQl9-CozYMy9d1@@u zrh*Uj>UcDqWpc!H#w zMUD}!H0%5AF%<1^(e=K#pIAVLoTu(A4>pGwX&CVcn(8onh`r`qIqKom+J0$rw)9{ZO7{99RY0w)C7zpyi)@dBh{PGpulXuWp3AOKU^RZvdUq~7Ccomvx4Tf0OUs3P#*|vUl%~oX#u|91^TCO?Vqw>1?EPIuBL#9JG&a7 zosqSY`@>)jfRpoYz2~3JARiE;{(uWcEu^V47K$FA5J|T6n|-rl9-q#_=Q>aFKSUW$ z`Sd&C_=6NaY`XY`T`Gqsa~}yuf~cfIR)2>2l*Jx3=hmadspu06fT{)hxfjpu6p5qD z_N*Z6w3#Hca5tmf8lw8eyhLcNtjZObs{k+nC%haaEOK=sH!zh4d3KaNy~j5TA6kYN zR<>ozIKQ%ce2)7a=CBr41b0C}F}vb4=bCvhhs$a5h0Hg{t)nohDPquPtQ22%nmvKc zF8M9bC=JX@|0J>9I2Tq6^ejNr*fK;=(+Ia!%7U{oTs!JZEyHoO z>OHnBtCXzfV13D;o)!pV><3(6KSkqDq>aVd#?Ona$f@9OZWD+$@<%*mv4E<3hf9s; zbo(;g_!pPlTe8hR50U6U!O!uLtNXU@PLR*fT~VlfjP6#y6SHw` z)uUKYQV0%PdXB}aOGPDZqSD%oqL2L`(E(6}O87C=){~Q01&`;cu&@hSS5g0Pb}6q3 zRGctX7`h8;q~mci`MD%Nm!{$8a5V10 z(C)0M(e=EYMK*{?x89_Qk~ZVx7%>8j5|DGR!~{8ofILLUkYD|tRNdZIiNz2<03jHKW+S6p4xSiJBJ)q?4otUfa#;$8J{Z#;N+*RjR`J|2 zbug~FqCFFf7VWl)Hg1@A;Q1 z9p2s~Tm7K%@YCVgcaRIASn1NR=}fCqqpj4rYnRBWOoGmoqxpYxcij*wqL~K0iojKVL{n+r+B)8?>B+#o~C#=-@$e120~CXDTL* z{c*so{kO8hzvPV)6^2j`(^!5XwLoClY~Z`=zZ?G$b%t?QL7?S7b|}pd2x*QBdAh`s z(mZW;zEr1;Si>zp+d!bpt5rv{QqL_>eF6UGpS*C#?Bnw^tM&B z|6?EW{=eIYqCu<@`Gur6KsJyZkXjjtU5s|Cu6svy#}!mY;5R1U707ziqiKH^EmRInl(r&SHl;iI5~KEODz8bD3KUGatQekpd>o( z=M9mp%luT+S$Lk>tN7gQGo@l=Z;G^t#8l*jX)yy>$bGzNpMH>rdJI97*(Sg*!nEDu z(P2jYE1Ly|u*_GqbuzvNalzM zpf2!qbieqcMF@-)rH$kaV4=d}Ff`f#fU_8h78mYV>C0(qt}SdWQtmIHq#YFozwl9i zqQ5mZ)wTrubR2F{L{dnO)uC!GCdH{H0%n5h7f?d@Ux1S5_?UhOM3G)|UE4(D05gvI z`$G1Dr914P1m5{3=jnf7uG)~38D-Gr)N)zFQFCOXLskd;knKb3%H#+gMZs;?M1x@J zO$(*yOU_V(xuOATM~<~{L+kFX(iD?G6pJ@gTpDK07xOn8|8Wg9Wx&lYy|DB#%T)#h z01_!6$W;K%Ptl9!r8A=dQ~fEoI}v)Rt>)Lsr)u>nO+6_FUvDmL@dbBo^8s3`$WI*2 zSDEe!hWf0P3%%XiWdDU;c-@db;{jn#ZAg^;#eiRUIlp)&Z`nA=J7=G<%LG#vjI+I} zox@YA!@0)RCmWT95~XByJ+a%j79t=I7Qk8Soc|A~qzAX$(1Ri(KE(oZIH*G#u|IB1ftuzpQ6!{-fly`JJu> zO^nUkUxR4-TLXtBN6IRBk*j$XDIJzgEguxG;2NdM$NVc_Lk3k)vXHgG^ac3|JklmI z=d!1L(6&;tWUM)zoI<^cFA;QFJf-~J>>ug@yVBfxFmRQBLj#$(ysG;!7NZedTb#u= zAN|L{v0b|V^FaawfxJaw`Q1r20|Y?%e+%UQ>qE4qX8re26#jdrHtoGfi^L$5e-oG^ z#RG&`)>;6lnNvCWH(_Kvp!@Qs=CPpSr@Qeo^~ghlAr(G10)+Ls>zb*NX?Eks#L4sR z?*0a{gi|VzXje-wzE}$;yL{y>_;mWz(beYylH*=>W_GqaINm;LPDJw6=uGa0-_aH1 zc{HOf&mFQGv%9vd5O^sh?{1l5{C^ zmJ8Dso@cR~oe})Kh4`m9u~e910X>oO5zmM{LrgOBSvG)F zM(V2@s3gUn%wM_ZGRf##v#Rtx6$un|(W8ZO9^x=`DP_80{Or61a&INXWS3cxvDYDp z8!4n>G(P=C(FU)1COOJ7o@59-rM@`G-{J2V1n$)Ei@00>ec5VTe--j0>43~FN~T=_ zl*H<4{ex?~u+FZ3klDgvL20l!%VcN_um)m{LIJ~%7Q26ZBf@eIx0A|fv(FDELqwZ# zoM_!3xll0)s@A0*)?1B1$*)EtCmgFbb6xPQR9M;8$W5$~=$5gsV~h6MtJD)Qwu}~3 z(-EmH&r#T*J=J{WSg*1wvmXUzlX=ys-H6~6aQXfWznxfQo+doOWezM(^7*_2^mxsx z)gsz(B#xYh5${f)k2z%p#L$vMRAAS#M^9vDUb1t>V;3*CI~h2*EEYYocWj0|Xl>Kz z0O~FubuiDeZf##vI3ghLlUbF8Wp*K z?|e#{WN(5T!P^G5?i_4VLwNqkz3|yh<-&b65D$u%ta1K_jyPw z08qO8xF;otpi)ib*i&Vv3SmT0kdzp7B@top(|xzG?@-tZNTc&qdHlI&SH zzZ^LXGJ4#g!bhpZX5_t#z)H)0k?pk5elZf zjC=&B8L1Hl27D%Oy`u#3ChJm?bnBs)4z_qz{aqnatmJO0@F}*g20RTFOH6fFCprv(@Q7o<5r}mI@i`s-R9RBE-OtAYf{|pB{|KRf4TX$8pO_67hwJ^WEshy zJ~PaklZIb$bLN5O-fip1Z&c0*SqD<`eOXC$#vpLdkgM}q!1r!KO#h-!k+H9e{SQy- z6n!cJdZWe|k-4ito2bur{emb)%_@YFk0E109YW(sQZ$0y2K=K;5Rxkzvzm$(sDe4E zK29z(wVZStFN#GvaX)<~Ti${+l55|4S8x9t=w#}@FOA;n+TZ#0(`K=6$EHp(#IX!# z7^p=Wc~S!TC(N*FhAT--gzumD-o_^wuZJUbs8ql8r;HtL-ye>45=~3j)G>Jg9-EHo zRoHp0yitfwlM(J2P=oh6;hTiuK)4$fNkh-haN^KMKxESgn&J>}6>j+5h^&P|y?nz- z)w5yO%||Yb*ug)lzqLF|$HJ3HUpB_fEGCt|#V52T+r~a=0$Y7R8zJxEtcrTd<|WX5 zrp_C8Ek9M$P6tmhuV&BFV___Ty`qaVZ8@}Lf&KI{{g)+nYu zBBB5h4Uw|-(sNxT6fnz5*|71fE);YIV^wb}$D_8vqs>5xE*?NN}3dG8EibuHg03 zizwcF*^Yhk3Lq74U(u2V3TB#h>fxA}K4a`D82wU7MHVVgdsvFH?92((mf~X5lzKJJ zE_QmsT!vouY5a*ap#w!No>CiMGB&toZUr8I^|Cu4f%bNzanyen3ltCp&8}9;dUp|! zDEiDYt&t_Nc_(P(Eh#@(wLyvm3Qx1hUAo{v!_WjBr9!s>EI27HWgim>OtG;Jl#iC%-T{IuZ7YQfdN3E_`Y7UG9jpaZS5-rUr%q2U4QyZK0 z=0tSye6jW;E!0*cDJ%gRK^0wwX__PjG6CnT{`iuvy8{}#s8&r5mfh<}3FtX0J5kb- z%^G9qGG?0O!5Y322vyKw?*6m?IcS`1d35x(3QB2g+0FJ`3UeZXB5c!mg}Qbz2n&CZ zLvMP%PAReq|L^o7QPG04~#KrWz8%e)*N)Y2wq>fz50LV9g)R zmPdv^L+FRVhFQlZr%a#kX`y7Ve8$|iX_dUBn+4}!LA`9C`a&N$(g>FqFL)|%=jP(O z+dB(m=jBelzKV#K&mK=xL&gV~xB0X{rg!yjx6d|uZ^G4374si?(S#410=oJFo&9n9 zeN#+Z3nG?042vG7`?)NRLIIO59?EL8H-t`u4#-}5oY*{4!tU+DY z+dO?Z4e3gVLRDHGQ+yul*YR2fOe ztO*#RcJjoHtIf~7B*`fTsW*_SI~HSV_85Z>5f%eU5m`=nbHd;|2~>LBjCVqMwZ=7s z2N%6cBl|gM$gzN0n>wmxk3&tGAJumck^r;&%W_8t_`1ojxQz6RstGdg3s-d<04^UumJ+}X3I@?2gsmEV* z?X9x?*G>P|@blXhBKw@GVq=s;Dq}ltRuo7OcPMRFn?$c&a&^s0S zv2be@G|4cp-JQepcu%oJ4vgNz_#U{1tT_mPHfohhmmU5+WN z@F$6LfnZG+remaKMG@-SKaehW=9J>&Kpdwk6q)ovxvnL9Ac9j}CGyL(_7l8Z28*_6 zVD{F=!Q6+ESNH178{p7l+Q-}g%`EdvGv6cT^xUMcM-^H7a9-;*IA4kWk*C27$&K!j zoZ|x{D5`aP9f~;(eL@Uk+{R41<8=D&EgADQY(z=RVV3@Tb&{H8jDIqyHv6kW=W*DsxH%=c@aM!MTy` zr$3|>=9i8dcd~*dUjo#xGj;|2?!OorD@DaF$bszKp15k=R$0}&zo57G^0MflB3K?p zO1aB`XoKvlm`VQMg{$rb&L#N6%H@qJ~w3zPzqPF!oWi8sw zHce0xLSN(U=~xq*i>;)N>iHFf=*jf&J-6E5CJy@_8sgA;?nWi|Z2Mybzw810tvl^q zhrdDeqnI+rBJ_-dsv(2vfd@g8FvEc(qQcJOjJu-V%;7TQrzYP- zAIn;pfFdWG>!!5C@ggAMmmo^Biko^)vn${1Ya`xqv@0qxTTb;A)eC0}<}?=CUo(Cc;oYudQ!aDm z4{<}tLk5^m=|4<$UQ09&*SnG$l8X$g;6&Bwi*3Bw``@|3f3JWtw!iGoU%?oDf&`G7 z=^2$~B@Wao^O|A}ReWCR7u3bv5~lF$7iS2t`tb~XZ)t@=?4)G1a0nxJWFK^Y+=*i~ z-alVY>N-iFP9@eOUar$|FK=#FSLoQbG0g)_%uHXv$|y@~;ATT^a{ieJUotruq9vkD z?T+0gI_M2F;*InDtoYvRB*o(>}ZvW%RH1nTo?drf>MDK%U)r^f(^QEXW=W# zyk0q~W#?r@Of*LKYPz;!?!W`oINZ0Po1&wT=G*CGxd_Fqi+&n}o{CWCcZAt5g2k8% z+TGh6f`J)Ip~8@TAM_A5=#Nr&hfo^{7ISNOxMG~FO>d@_Wr}M9hF0+q%ew%pwvzYZ3AcC*5LxPD=879+CfO@F}J|Ne1 zU+R87IeSq|@fR^JEr@oGJFja8Yd{IcL!xclP~wxOwR~2RTN;fpo6RM}mbft(ELLs0 z2w`eqB5?xhWf9tpvsSM*`%2X#Fh9Z!wK7T+AElKcS{b1ff&NptENq9`^0AFsn&0+sSv+u$|d8UaN=8*hn`0yyy&oFUY4(P%@A z4g1Dvaztfk>#BXDDqy0JRY$o4rh6Bhqn^V`hj1TDEM(-z0}e&pGCNknwnkPCN3r)i z0U1uYD{ooQzqeD!alf8&%sE5Qr5fx~yNrK6IeImP0g*#bvO=J-9x7TR1>$*RrAy=H zyuMFWrJnzklFJt6C7v8q&FrrLO$1D3;cwQp(v@@+&eT=|G8I;D-1pkoDkZfeFN}Bd zsv{RUb|Nfbt|FFSZOC{U{uRqtzgSYZ?{AJskc7KP)OJ{Bjof-qheFtA3x~|$ZF+VD zi?!yM4E}UJE1tS}C@;KQ%^7;$k4BR1m6c%5FO z#-vU<$CRSY*Zuo?9DZ9Yz0HKIS^x^gj4G^^$tP(%q>MX5U7T2o{_xI^3-%9M%7F=I z!GDF2fYg>fZ9|@l(gM69yt&c%gvw=rP8W1vr(}>J+_(n59A~buIM&uoHmre7xa*$; z*4W^Z8`CgPpydY}UZBupd2h%1PVOV8eSUBxtF5=yYHR)!Bi#0BHKxE^lY z$G9#GUfvJ>G5a;ak3a*bS5P9CCs#o78!|vUP+tH9r4UjJ5AgVkXAM?cI7RfEfv4~R zuUpJBN-KxtL%=v6=@U?CosInxY+0bIY{Wg_C&6I?)uLQnyr>eHaMhUGjOVH=SmMi< z)MzRxX!K3xVr!0Z1S=*oQ1S2t7S!t6nXOav>4Gq7wNx;628AmZo{FPa)YQ}RS*vtq zv|K|(WvTF)WF!U=wg?CK`D^S2W$RmRM(?$D#>L~lv5AUH?JF{vXA@qd*(5Jq*3}Q4 z-f;X-JR)4sqpB;$0k2BuH!i^H6HRCPh0V#6MK|zSr1}p{;8%BIp(-z#V*sVLt(!&?-TLx=OZW5ErZsL#Rk@ERC`W2=D|;9<19t zq2r8*x{4Am4b9vm6;t{`O{HHBR4^_FUdA}O5A6uNHy^)XN5CtQ&-~M;LOvIN_9?lYc3_B!>cFk z3WsMFPu{-`PnJ$@zC>q*2lPwo`@phy(|x=Ee1AszzPLlc?iSrgXHHEKnUTcMDU0Ts z6Rbm)@*Gu7&{AWgjX7bHpjIk_+anC#>G8 zc-mifn3EQY`?qYN59MVxTK;L*w1H{3p);s=tKk}G(Tm+jAOY*{m*VDGVSE^oDWh{^ccGL*@abQe`ex9OQf>Mk1+ z-(~>PBH?O25>QnwNn;V==-c}ez&L~Q&fN%|uYUyU3k&%P+vuwq3^W}`D`tP!X!oSi zVC(1G_~htSl1=n6=&X$4rUUqj?3o_v48=Wg0UT`V zC~%1CAPkV>GKj(MOE1sDu5>dz5n(EKK~#zOURJUq=E7Ox2~he~a$a4cd@# z$*0W0r=;N04yI<+t;D{M+Jb5u6d*kIH;5S{*ffw|kkSiky=8#Ya~=Jua4`NVA}h|8 zMX3A*>Y1m9P*dwe1tX1QxY9cqACc zh7mQ#hVHieTKI{u@V`LBJ)o=VgX(Aad--P`Bh#X-wpOK1|hIo$rCeu?uXlk8N_L4ezCV;J_3Rtad0os4uY!D0%a&+UWAx?Itl;bL z`(p5YOXXLY=AYfI9UP7z)k{r|ITBJ2rsEQ+%>XNKj{>O{m2qf_C@LYBHy57$3=<)@ zlxP^jX>X`l)u(gCUUk)XG_<`?d^~Hk0z1Q#39^H1)`liCr8NBc$@{7@YMXRM<_f6* z*o~VC^K7+o?bO60hhwPyD|E{gaDfuNqzqN72^LipV|K+ zYy6Bk>C9AwQ01zI;qx>Di`LM7$r9l$Vd6!i3anssKi*=JK7X@ET3Cmy{ni?WxOOHT zXS35XxVc!jqb!9ubN%| zr3t!1V8o7EmoQR>SeJ(o$1~)Mh|;aGA47 zAFH%})v&YzE0Ck&F86>D?-PBZAnQ{i7K&CtmTvR@v$wF-wX#q+# zo97L^d9N_4HWBqxz|jRW?jJNTd*C@Hb4Z&jMl(Yqv4NliQleUl{jVSi8@^%Q@&Qn`shE_$HO6D5T2OZfp|n%<3d8_Uk=&7n+0o)UBUVcU9n&Q(X^&FNgdsY8=4v_NUd~?1<;Q306228&^C z#a}^_tLo~yw6peZ|D+><_-x#zJ1){F5}`hUb1x?pwu9Golo2`y^bSUud3Cy_tx>l0 zv2oP;!d_V?Wd|Vl+-9+=x>_iq9?F5G|N(oA1)%AnZuXHlDlx<4#Q|!eUx-{oJNOrlHj(M)>mN+3{qWc${taMS&^tk z6m3~sQ(<{Ii5bND0=|O9^2^h-sC1?EWa7IBLhSuR)#JzM2j}s=1ZnttsJo3dsVmwv zeeS1Q5J!QZ>0`Ios4rR=xFE{guC$!$+CEo(Af$yt;^&D9Fok=GB$k@}U_)hXWmGJM ze<7Fvj|cSj59&j`aO-G8e*>e{gz?8x4^y7tME zDB?kVLF+RL{2SLw7RB=|84H#A287Y+BRwQVEMdi6(};9Q{-t&boex-cB!Msbz`TsZBj(+w!q@%l z>ljJ3xPjvPb+#fJWag{(qFQ3WNrDDNkUuIqr8rKTQedW53-8%b0=*mw&-uYg;98AZ*lC8= zhLqZ&U!@X#VVXR&0D^dY*+?l&>Ma)Xyl}f{OzO#-UZsp@uh@pp9*xdA8$^8&>8-*# z8yc|F1zJhhx0JqyfVg6>;HJRccA3Y}xR>K@0->a&IFraDTg=oNvzy5N?KEG~mCp*j_{2T!jlN4*% z&!KvALlE7U)VtqMe$wD^znJeRaI!HGpY!9b{x{u4G!fH}yA=~0+65Ifj*TI?gS%Jn z&r&aeW1)I8x+-NP%u#Ej8O7@^^_)r?CMU{SFVAiwmu#x~nm{!^gI7L<@z|8=SA>hE zlPDZv8d^)IY9rNCviOgm(FgHF>Ba0mJyX>UYU6O9E0o%=xFGB{S6ok;xM z)K7rS^N+({9AunnB<_2q%r&SICDY=MS1T+iEk1~d zy^poC)ub=49-=sLnpa_K?B3tvwFdzL$2SK$ExR zRoqJ~;>r&m!#-cdc>0PWOW~7ql8|+(ev2lyP?&Me}6Y)OC>X`>t1|FIS1#xatmIAh2H8LCu(9ncOYcuUgUVY$#S~7QQLO zvy~{IuejNWr^4ZEsY%z?!AUsI#Szt&DKSF~4$MHx!=}+~pY%kAiHE|4eO1di{NQ!u zZLq~{FcdEN`WRBvM}P_L{)0#)bO>vvb92sjs8LTDJCQM z3C(g(u59msV$SC!&I-vo+PT)qCq;DbE%RLBjq~CJBJvmn6CHc57#|w@9dmQ(q>0P!mX>+sJu^} z_Mi)o*t{H8*qM@j0nO`GX&wg$9kH_wEOoE#p1X*Wim&vs-CHXh%n=0Sja4FZSh`pD z)tZ5iGG2r~Otb&w6Uc1}lysMcjpW5b#~lreP%w_*~g;R7k+)VjxbUvT;qM)d~eZN5yE!>rgQ1rhS@|J#^Mu(9VA62p5kB zlr-FWYbgv_bWZSho*&ygyR<>v$-Dn zKzwl+5eEgASnCm%W_$MXU_ezUbc%ZPhPmtlZzx&MYc$$E#*T8nCeuew34$rNXpnuW zPD);K=DAq=iB~EK%zPY*Rquchb4v0+Kbe%8#2j_GT22GZNF03M!x9X_9asoLTMDeO zX3po9hme@`b3WNJ>C7fz>2(gKSqd2^Jg@u62`kELUmnc*Uq_D|y&7((ZR7Q1T;1#kMHqVWG%g=~$ zyuoJNG7@hk%PvGqqlWrezit^>@s_Ku3vpBj>Nu6b@^bdEsq^d1ZM(hprt3Y%U_hYR z#hrZp;Te#M8~>ib7Hvc+>Pg9T#o*K3!S}mzLl6zjg7Ya=0ZtcEw~srQR4UbjTjO6B z+-deIY_xJ$DeQ)*8*Ykt6;6W}ur_@Q@#l{CCXUIj#Hc-*vsJja1nZjK%y=4KY#eachx(r}QwSYCDor==&y zNKSkFJ>FzB>lt*zF4W*v`L7LwxaaBLvY|_%B2;f^W#)h;w$5P=Ut%!bD;oSxiy{4c zA6PT4P6y5?N<@?GR~(*&ihznX;wGI9bg~K&eFpd;Lj*Q;9v*IvcFT4UL!#F3F|ITz zL>+^^AyFd4IQ>1PJX-b8i}}Mwzg>b0O-hi(Ii=h;$>cu{BvTKtkFp9&u5@}fOq6b8 zc6ww)rx+_3Iynn6N}q0vKP24Oan5O6+2va{tE-(ylJ7cvK0f;y&MNx80@c>;I9hMo z1CrHfzbP15qba&36yOktRXvXYV!PQfFZ(j>>I|uqnjyL|FFt3HNjMt34r!72V7gU- zYzg+(kfp0}^K9%nH!i}i?)v1q&1U0miTI)2at;#&UC3-JLXJMeHvY5)8HbvI#q9TeGF6iv?U?oIs zeBEf6Ob&hXCHsxDScKK%7Et9!4r}CF?!~6j`Z^69h~-}m?8;mwI}b6{R*tN5zCUSX zkL{FQETlGj_e!pfj5wS;&sZZ)O{@9zr}2MMO$bugDiG5 zn%WgsI@q--#@|wC9}O$)n-cB=9X&wDRQY4d7oFGhqD78V?E}kpMbVX)qEBnL;hq${ zL|5~-_$a#Q=KbuRTPHqmW#7^Tv((hE`tYb;ZAso-kYQqh)s*Tm%X3g4yG_BVm)@Zr zP_w3lpw{6ksc_G%BxpaT->plMBH$?unb4NyTd{kxZL8YDQ7^4_CB5HQED1IUE$Q!I zJ=zi{+ZaF$Qb9?U#F+$pr4YoS1fbHjytrb8ogM3PJW@rbTyw)klBduM!bGA7Zhq4; zN@yR{CX&vH;PT*#A)SZybuh-0QWT~)Dik%%_LxY{p_?X-mww4rhp&emsWF=wX#0KK ztxfw4@gD|a&O#UEo&&!4I3|*xF;o)cGmK2x;5>lc`;C&f(aM~q+jzJ2cif-JKg%CZQ%={+Y{cuub2fU?@_xTnGAdeG5~TT!JRmq# zLnYT%9X7HDR!Wx3Y%R~IMWTXKF4m1a%{apN>uo)y1kCf+Hs4lVH~Kt*Zjttq523~{ z#C6TZ@K4pcjA!dEqbL$;orbrwS#Dinvel~@j^XnH$`?Pjsfun#yeftr@iFd!csjE` zVgfhsqx8Z)_UAy=uX;4!lK7--Rxw|P({XUE`V-E`5z}Oyfbw`tP%sGsZWeurMr}#pcXE=00w9y;+*PVbtpuwh zU98>w`AP>JcE8In-pp(M@mm$>xoAZBG00h|%oc%})@TBzl@YhxrqXvPT};+8z#O`o zBpbaJlWw5~7obamLwB@iH^>8V^7C~yyzVOIBGjW{JM5*hKZH$=Iph*SV99)qA+kmLS&krvE)Rpq90{ zmVD2c6~*)CdOm|TCVM9p&!X%G%24$AN^9Gww%Y4IDD~wEx5Ba8(s%AsSJ}tgBO92L z@x=wPIMK$@u?cIjMF=wnT#MvVB?`Oqd9>HnGaEii6fQ17d7wzd;whGUPgQ<&X>GrPTcynV~^;d7~|{LCkA?-tjn z{DofLF23|40Di$TMN@Qz{^VvhN_i`>C*AJDRA5n3^5}Aa-*g*-E)eEzFtnOT zsv8A)NM`kLv7Uh69s;p1C5|Y-Xb|yzMMvpqmkXsME=s~Y>P9rC4I83Q&|T?lkNKnR zY9r>^@u}(M4?Iu;BfV>8r|@(SI+pCupNd#r5M*|De>1i^${+DetzMC+v0IKi3W`1V z<>|@wH|*%EZ6w^cE3^96#!)N7#;5A@jiF}>NA0=f!h$nx)HSJ7)nZZ8E&KR2=#r4r zQGsJD@CzG%3*R`ktx#6UoWXc^uc8!p0nNE^sDxWi9OQgYV8x2uAycbDjFZQRmzJ(S zZ+F%2W-R{Gg#~|A9lrOL%@;;}n@nj3!clTv1uRNov$>f4uHDy!Q|7S^TnwJk$2SMr ziaEpM5x|m$$)e zCcK1H*Iw$ncqBHrh4+HmKrl;Yq$_C3mJT)4IP#_IBR`{PQSAwZc*Z6&@`2LF+pOO!OcM7hiDQFDpwe^+Ri^SgOpY-Pw(Os{c#mCf z#~56mpR4a)DF~GIPk1Q%W0>L2S~s4!GJL75@R%EGIzZDCBjagIo)7~YwxxcHfDHD0 zx{m*dF~h0}Azg4oyZ87QJ(EN1EMJU@3P-!*B+nkuq%y`^WY(C;RS`WV zRxS3}nO8KiI<_eO4D0+3!{X`>!Le~*v&k$Ydc(dVN)LrwMO6Aws}6yfBekb2;;wDj z?sSx|BJ;>gagpPFqUpk2P`sKL>4`REHO?L?GQ;B)iY&(wpY0!52Fv}TW@xG$HjK6iH;R1FgTQ4;*&6(aQ26&L5gkf|OyxPI(gKi_TWuvD$RSXy{=oz3NV+L7gIemc>FBj=O@_jUgKMDvjHD^L6x-;oGQ zca{Zj$;#otj7~CgItHq`U?wn8$yHz*^hzsnxOIH7b#jo}X$6ul>8fscU-_j;`N1OR z)Kh+(@hm$Vh^bw|(1eA!(?L=q^K_l|#+c5y%5?*&US0HVljP|ESJLR zQ))XP>3o@N|M3xSAOpERK1}97J5TRcrHS-(VU(hW0Ugv+Sdujt|C*|rWjJCdf*fa_ z3wm-hN+~AP+7hS6u5g2$5Pmfg%|`Z{VJ`7uc_L-8p0|)MiQ=~UDm5Oo!<>Rq35_YV1d2VE+h3U* zBAXewEv=L0)S8+Sh0k3y{20vJ5x)7pq+NIAWizqs3oxuvx`w}d#>!*`n-3GJd5((# z0AT!Z#>(6VDndXHwlDz7BLU!uVQY=PU$%D002rw5G63+$pN3fRka$M)&i!*NUsD81 z){uu{rLt(xD`YcxK){NaC|xu^IY#8Xr zC7$4&ob72Gi*V_VQ-aISqaN0V3*cv_Zru#^_r-JUD@)L1{Q)V*=R3?a0_>uvU8nUF zVy}&)@-G-Rb|9#zX`d*N@zM!Y)4MTzZA8K&T2U=#!`PvUV%nf6XCjX_EO9j}I5GV4 zu2B(PYJPP7d_=qtwQ}iPxrLGN;oXRp54){s7f#f`LHL?a%>>JFiTthNv$(sgg*`Gh z=nix^tZ}&9iNvxuBowWe^AD_;vh1oJ7*eDXm94#w-M6j?Rb5mWEq|7g9$TET2`hVE zT0$Kb+M$e|_fQ5-#&O&6X7*4anBDOxtNAPa!F7_Uyv?X!WKw&0)V2=?GHC=5AR&;y z(RtWiiAwExG1@?=M>ws35~=;B5pilt$=4TycKkib?u`XCInW4&d2X~vq{ma$1=r@`j7baJe6DJ;nqp zPP5$E?qOn@-g8lSdgALf%m@^dK;^`KIHa02P1VJ}hK1{!Y*mkZ%@MIRRH=EsKppM0 z$ZC^dkd}(+$tGO!;V$mtbK*tu#A?F5kN*7Z>VFI0K4y z(y`d{K+dz@>u(#eY}n?Bc$grs22XZupWetZ{c<_;92OaZW6}fP-nYEnK#zoS1=vS=LcjOaRY#h>!Tnpe7 z=6E4|Z4mV6%Nv70S-uClUSQ>0%7u9xNW_X6kS`_W3%j+g;AHj%d*{2Oe@Oh|RFusY zLVL><^umGmE=eJIemc>&!VJ1#a~o}AbA2m%J2TLK>tgD`%@0}_(O>Uh`xh(b499zB zx+g0loWSYSj%(Ete31XTFX>3NY^gP0pHsO%5b*fhFq5$ogCa>NEqm}DeqoGYjhmUe zd^9!Qo2gq{7D<`bp$HvJb$LC`KpN$Cm>g{`8xc`SHnxyg>WDHYeL1$oE3xlOjqdOF zYK;iCS~hWgTti%sqwv9b?GwbJe*r(HC2%nCAreirL)90rOv<`b=!JU%>rtm%_qm|D z6U^PQg(XH%2?BlcROm%__vy{(p{Jlh`t-&+V6dq*y`HhP1xVYT4s2m#3^s>qpZxcr z=m#;O!jhr`E*%l3M^;~RAun=jT18Vi_8x5 z*!dBwLj*6;HS$Tw4M79+m^Tb84;<7S0{RiJC07M&=h0$8|Nnj=0&u_I{^OGl-R}Yb zm>HYt+t^#^1LY9_F#j@m{)zVIcfX^(;ta`=hklb8x)OzP2TcKrCM6^wEyrMEYy%CN zosrG=`1~5IP=P=4DG30;GXMZQx&wOxCHoWBN?%*g>^E_l15lsDK@ozX#l4IB^66i= z=3pCR-QUEekggv`flfxN%m4uTo$?YvMRWcvuemlc5cYQOuv&PUd?60OlP~ERMfGLC^r0TmNPZoQ*!J6G4F=LCqeC?f_%( z{002olUdXH4}Swq3vH|4r6^LhmxD(H0QQ*xfX8^^AZ}Q6oXdT-flF*tMh4y;lI|Mi?e-Y?{ZFP-w^tH`2 z-x=#eesqWVwYG^9W**B8&8PbCzKcTrIE>V(|0j++z81emg9=JEQh;_LYFHQm{v8@w zoqwnKy-IfuY(Iexg8&fYKkMSk=VyFdTVuW7?8EgSMTQ+zXdl)C{Nn*+LjQ%p#u)T_ z4}gqb9=8i^NSlA?cKlcmVM#yZTigDv;_++o_g4&@Xn+nsv=K+v4SS>*20< z%#Sott^bAQ|Iy>_8a({Sq|)^tnSQU$-W8PlkwS9zXNrH3m;1G3{|L)N0`ni!{9nVq ln>PQ5%|&_#`&W|a|3rxZ%~`%D7es&_=+uTs2AxC!{{v@Uf|>vT literal 0 HcmV?d00001 diff --git a/site/couchbeam.html b/site/couchbeam.html new file mode 100644 index 00000000..e54e42ff --- /dev/null +++ b/site/couchbeam.html @@ -0,0 +1,2386 @@ + + + + + + + + + + + couchbeam — couchbeam v2.0.0 + + + + + + + + + + + + + + + diff --git a/site/couchbeam_app.html b/site/couchbeam_app.html new file mode 100644 index 00000000..5b630038 --- /dev/null +++ b/site/couchbeam_app.html @@ -0,0 +1,218 @@ + + + + + + + + + + + couchbeam_app — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + +
+
+

+ couchbeam_app + (couchbeam v2.0.0) + +

+ + + + View Source + + +
+ + +
+ +
+

+ + + + Summary +

+
+

+ Functions +

+ + + +
+
+ stop(State) + +
+ +
+ +
+ +
+ + +
+

+ + + + Functions +

+
+
+ +
+ + + +
+

start(Type, StartArgs)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

stop(State)

+ + + + + + +
+
+ +
+ + +
+
+ +
+
+ + +
+
+
+ + + diff --git a/site/couchbeam_attachments.html b/site/couchbeam_attachments.html new file mode 100644 index 00000000..419c273b --- /dev/null +++ b/site/couchbeam_attachments.html @@ -0,0 +1,402 @@ + + + + + + + + + + + couchbeam_attachments — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + +
+
+

+ couchbeam_attachments + (couchbeam v2.0.0) + +

+ + + + View Source + + +
+ + +
+

This module contains utilities to manage attachments

+
+ +
+ +
+

+ + + + Summary +

+
+

+ Types +

+ +
+
+ doc/0 + +
+ +
+ +
+ + +
+ +
+
+

+ Functions +

+ +
+ + +

add attachment to a doc and encode it. Give possibility to send attachments inline.

+ +
+ +
+ + +

add attachment to a doc and encode it with ContentType fixed.

+ +
+ + + +
+ + +

delete an attachment record in doc. This is different from delete_attachment change is only applied in Doc object. Save_doc should be save to save changes.

+ +
+ +
+ +
+ + +
+

+ + + + Types +

+
+
+ +
+ + + +
+

doc/0

+ + + + + + +
+
+ +
+ +
+ +
-type doc() :: ejson_object().
+ +
+ + +
+
+
+ +
+ + + +
+

ejson_object/0

+ + + + + + +
+
+ +
+ +
+ +
-type ejson_object() :: map().
+ +
+ + +
+
+ +
+
+ +
+

+ + + + Functions +

+
+
+ +
+ + + +
+

add_inline(Doc, Content, AName)

+ + + + + + +
+
+ +
+ +
+ +
-spec add_inline(doc(), iodata(), string() | binary()) -> doc().
+ +
+ +

add attachment to a doc and encode it. Give possibility to send attachments inline.

+
+
+
+ +
+ + + +
+

add_inline(Doc, Content, AName, ContentType)

+ + + + + + +
+
+ +
+ +
+ +
-spec add_inline(doc(), iodata(), string() | binary(), string() | binary()) -> doc().
+ +
+ +

add attachment to a doc and encode it with ContentType fixed.

+
+
+
+ +
+ + + +
+

add_stub(Doc, Name, ContentType)

+ + + + + + +
+
+ +
+ +
+ +
-spec add_stub(doc(), string() | binary(), string() | binary()) -> doc().
+ +
+ + +
+
+
+ +
+ + + +
+

delete_inline(Doc, AName)

+ + + + + + +
+
+ +
+ +
+ +
-spec delete_inline(doc(), string() | binary()) -> doc().
+ +
+ +

delete an attachment record in doc. This is different from delete_attachment change is only applied in Doc object. Save_doc should be save to save changes.

+
+
+ +
+
+ + +
+
+
+ + + diff --git a/site/couchbeam_changes.html b/site/couchbeam_changes.html new file mode 100644 index 00000000..06e856bd --- /dev/null +++ b/site/couchbeam_changes.html @@ -0,0 +1,566 @@ + + + + + + + + + + + couchbeam_changes — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + +
+
+

+ couchbeam_changes + (couchbeam v2.0.0) + +

+ + + + View Source + + +
+ + +
+ +
+

+ + + + Summary +

+
+

+ Types +

+ +
+ + +
+ +
+ + +
+ +
+
+ db/0 + +
+ +
+ +
+
+ server/0 + +
+ +
+ +
+
+

+ Functions +

+ +
+ + +
+ +
+
+ follow(Db) + +
+ +
+ +
+ + +

Stream changes to a pid

+ +
+ +
+ + +
+ +
+ + +

fetch all changes at once using a normal or longpoll connections.

+ +
+ +
+ + +
+ +
+ +
+ + +
+

+ + + + Types +

+
+
+ +
+ + + +
+

changes_option/0

+ + + + + + +
+
+ +
+ +
+ +
-type changes_option() ::
+          continuous | longpoll | normal | include_docs |
+          {since, integer()} |
+          {timeout, integer()} |
+          heartbeat |
+          {heartbeat, integer()} |
+          {filter, string()} |
+          {filter, string(), [{string(), string() | integer()}]} |
+          conflicts |
+          {style, string()} |
+          descending.
+ +
+ + +
+
+
+ +
+ + + +
+

changes_options/0

+ + + + + + +
+
+ +
+ +
+ +
-type changes_options() :: [changes_option()].
+ +
+ + +
+
+
+ +
+ + + +
+

db/0

+ + + + + + +
+
+ +
+ +
+ +
-type db() :: #db{server :: server(), name :: binary(), options :: list()}.
+ +
+ + +
+
+
+ +
+ + + +
+

server/0

+ + + + + + +
+
+ +
+ +
+ +
-type server() :: #server{url :: term(), options :: list()}.
+ +
+ + +
+
+ +
+
+ +
+

+ + + + Functions +

+
+
+ +
+ + + +
+

cancel_stream(Ref)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

follow(Db)

+ + + + + + +
+
+ +
+ +
+ +
-spec follow(Db :: db()) -> {ok, StreamRef :: atom()} | {error, term()}.
+ +
+ + +
+
+
+ +
+ + + +
+

follow(Db, Options)

+ + + + + + +
+
+ +
+ +
+ +
-spec follow(Db :: db(), Options :: changes_options()) -> {ok, StreamRef :: atom()} | {error, term()}.
+ +
+ +

Stream changes to a pid

Db : a db record

Client : pid or callback where to send changes events where events are The pid receive these events:

{change, StartRef, {done, Lastseq::integer()}
Connection terminated or you got all changes
{change, StartRef, Row :: ejson_object()}
Line of change
{error, LastSeq::integer(), Msg::term()}
Got an error, connection is closed when an error happend.
LastSeq is the last sequence of changes.

While the callbac could be like:

       fun({done, LastSeq}) ->
+           ok;
+       fun({done, LastSeq}) ->
+           ok;
+       fun({done, LastSeq}) ->
+           ok.

>Options :: changes_stream_options() [continuous
+     | longpoll
+     | normal
+     | include_docs
+     | {since, integer() | now}
+     | {timeout, integer()}
+     | heartbeat | {heartbeat, integer()}
+     | {filter, string()} | {filter, string(), list({string(), string() | integer()})}
+     | {view, string()},
+     | {docids, list))},
+     | {stream_to, pid()},
+     | {async, once | normal}]
  • continuous | longpoll | normal: set the type of changes feed to get
  • include_doc: if you want to include the doc in the line of change
  • {timeout, Timeout::integer()}: timeout
  • heartbeat | {heartbeat, Heartbeat::integer()}: set couchdb to send a heartbeat to maintain connection open
  • {filter, FilterName} | {filter, FilterName, Args::list({key, value})}: set the filter to use with optional arguments
  • {view, ViewName}: use a view function as filter. Note that it requires to set filter special value "_view" to enable this feature.
  • >{stream_to, Pid}: the pid where the changes will be sent, by default the current pid. Used for continuous and longpoll connections

Return {ok, StartRef, ChangesPid} or {error, Error}. Ref can be used to disctint all changes from this pid. ChangesPid is the pid of the changes loop process. Can be used to monitor it or kill it when needed.

+
+
+
+ +
+ + + +
+

follow_once(Db)

+ + + + + + +
+
+ +
+ +
+ +
-spec follow_once(Db :: db()) -> {ok, LastSeq :: integer(), Changes :: list()} | {error, term()}.
+ +
+ + +
+
+
+ +
+ + + +
+

follow_once(Db, Options)

+ + + + + + +
+
+ +
+ +
+ +
-spec follow_once(Db :: db(), Options :: changes_options()) ->
+                     {ok, LastSeq :: integer(), Changes :: list()} | {error, term()}.
+ +
+ +

fetch all changes at once using a normal or longpoll connections.

Db : a db record

Options :: changes_options() [
+     | longpoll
+     | normal
+     | include_docs
+     | {since, integer() | now}
+     | {timeout, integer()}
+     | heartbeat | {heartbeat, integer()}
+     | {filter, string()}
+     | {filter, string(), list({string(), string() | integer()})}
+     | {docids, list()))},
+     | {stream_to, pid()}
+     ]
  • longpoll | normal: set the type of changes feed to get
  • include_docs: if you want to include the doc in the line of change
  • {timeout, Timeout::integer()}: timeout
  • heartbeat | {heartbeat, Heartbeat::integer()}: set couchdb to send a heartbeat to maintain connection open
  • {filter, FilterName} | {filter, FilterName, Args::list({key, value}): set the filter to use with optional arguments
  • {view, ViewName}: use a view function as filter. Note that it requires to set filter special value "_view" to enable this feature.

Result: {ok, LastSeq::integer(), Rows::list()} or {error, LastSeq, Error}. LastSeq is the last sequence of changes.

+
+
+
+ +
+ + + +
+

stream_next(Ref)

+ + + + + + +
+
+ +
+ + +
+
+ +
+
+ + +
+
+
+ + + diff --git a/site/couchbeam_changes_stream.html b/site/couchbeam_changes_stream.html new file mode 100644 index 00000000..56731be0 --- /dev/null +++ b/site/couchbeam_changes_stream.html @@ -0,0 +1,374 @@ + + + + + + + + + + + couchbeam_changes_stream — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + +
+
+

+ couchbeam_changes_stream + (couchbeam v2.0.0) + +

+ + + + View Source + + +
+ + +
+ +
+

+ + + + Summary +

+ + +
+ + +
+

+ + + + Functions +

+
+
+ +
+ + + +
+

init_stream(Parent, Owner, StreamRef, Db, Options)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

maybe_continue(State)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

start_link(Owner, StreamRef, Db, Options)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

system_code_change(Misc, _, _, _)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

system_continue(_, _, _)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

system_terminate(Reason, _, _, State)

+ + + + + + +
+
+ +
+ +
+ +
-spec system_terminate(any(), _, _, _) -> no_return().
+ +
+ + +
+
+
+ +
+ + + +
+

wait_reconnect(State)

+ + + + + + +
+
+ +
+ + +
+
+ +
+
+ + +
+
+
+ + + diff --git a/site/couchbeam_changes_sup.html b/site/couchbeam_changes_sup.html new file mode 100644 index 00000000..a6ce3923 --- /dev/null +++ b/site/couchbeam_changes_sup.html @@ -0,0 +1,224 @@ + + + + + + + + + + + couchbeam_changes_sup — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + +
+
+

+ couchbeam_changes_sup + (couchbeam v2.0.0) + +

+ + + + View Source + + +
+ + +
+ +
+

+ + + + Summary +

+
+

+ Functions +

+ +
+
+ init(_) + +
+ +
+ +
+
+ start_link() + +
+ +
+ +
+ +
+ + +
+

+ + + + Functions +

+
+
+ +
+ + + +
+

init(_)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

start_link()

+ + + + + + +
+
+ +
+ +
+ +
-spec start_link() -> {ok, pid()}.
+ +
+ + +
+
+ +
+
+ + +
+
+
+ + + diff --git a/site/couchbeam_doc.html b/site/couchbeam_doc.html new file mode 100644 index 00000000..02f1b1b8 --- /dev/null +++ b/site/couchbeam_doc.html @@ -0,0 +1,849 @@ + + + + + + + + + + + couchbeam_doc — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + +
+
+

+ couchbeam_doc + (couchbeam v2.0.0) + +

+ + + + View Source + + +
+ + +
+ +
+

+ + + + Summary +

+
+

+ Types +

+ +
+
+ doc/0 + +
+ +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+
+ ejson_term/0 + +
+ +
+ +
+
+

+ Functions +

+ +
+ + +

Deletes all entries associated with Key in json object.

+ +
+ +
+ + +

extend a jsonobject by a property, list of property or another jsonobject

+ +
+ +
+ + +

extend a jsonobject by key, value

+ +
+ +
+
+ get_id(Doc) + +
+ +

get document id.

+ +
+ +
+ + +

get a tuple containing docucment id and revision.

+ +
+ +
+
+ get_rev(Doc) + +
+ +

get document revision.

+ +
+ +
+ + +

Returns the value of a simple key/value property in json object Equivalent to get_value(Key, JsonObj, undefined).

+ +
+ +
+ + +

Returns the value of a simple key/value property in json object function from erlang_couchdb

+ +
+ +
+ + +

If document have been saved (revision is defined) return true, else, return false.

+ +
+ +
+ + +

set a value for a key in jsonobj. If key exists it will be updated.

+ +
+ +
+ + +

Returns the value of a simple key/value property in json object and deletes it form json object Equivalent to take_value(Key, JsonObj, undefined).

+ +
+ +
+ + +

Returns the value of a simple key/value property in json object and deletes it from json object

+ +
+ +
+ +
+ + +
+

+ + + + Types +

+
+
+ +
+ + + +
+

doc/0

+ + + + + + +
+
+ +
+ +
+ +
-type doc() :: ejson_object().
+ +
+ + +
+
+
+ +
+ + + +
+

ejson_array/0

+ + + + + + +
+
+ +
+ +
+ +
-type ejson_array() :: [ejson_term()].
+ +
+ + +
+
+
+ +
+ + + +
+

ejson_number/0

+ + + + + + +
+
+ +
+ +
+ +
-type ejson_number() :: float() | integer().
+ +
+ + +
+
+
+ +
+ + + +
+

ejson_object/0

+ + + + + + +
+
+ +
+ +
+ +
-type ejson_object() :: map().
+ +
+ + +
+
+
+ +
+ + + +
+

ejson_string/0

+ + + + + + +
+
+ +
+ +
+ +
-type ejson_string() :: binary().
+ +
+ + +
+
+
+ +
+ + + +
+

ejson_term/0

+ + + + + + +
+
+ +
+ +
+ +
-type ejson_term() ::
+          ejson_array() | ejson_object() | ejson_string() | ejson_number() | true | false | null.
+ +
+ + +
+
+ +
+
+ +
+

+ + + + Functions +

+
+
+ +
+ + + +
+

delete_value(Key, JsonObj)

+ + + + + + +
+
+ +
+ +
+ +
-spec delete_value(binary() | list(), doc()) -> doc().
+ +
+ +

Deletes all entries associated with Key in json object.

+
+
+
+ +
+ + + +
+

extend(R, JsonObj)

+ + + + + + +
+
+ +
+ +
+ +
-spec extend(term(), doc()) -> doc().
+ +
+ +

extend a jsonobject by a property, list of property or another jsonobject

+
+
+
+ +
+ + + +
+

extend(Key, Value, JsonObj)

+ + + + + + +
+
+ +
+ +
+ +
-spec extend(binary(), ejson_term(), doc()) -> doc().
+ +
+ +

extend a jsonobject by key, value

+
+
+
+ +
+ + + +
+

get_id(Doc)

+ + + + + + +
+
+ +
+ +
+ +
-spec get_id(doc()) -> binary().
+ +
+ +

get document id.

+
+
+
+ +
+ + + +
+

get_idrev(Doc)

+ + + + + + +
+
+ +
+ +
+ +
-spec get_idrev(doc()) -> {binary(), binary()}.
+ +
+ +

get a tuple containing docucment id and revision.

+
+
+
+ +
+ + + +
+

get_rev(Doc)

+ + + + + + +
+
+ +
+ +
+ +
-spec get_rev(doc()) -> binary().
+ +
+ +

get document revision.

+
+
+
+ +
+ + + +
+

get_value(Key, JsonObj)

+ + + + + + +
+
+ +
+ +
+ +
-spec get_value(binary() | list(), doc()) -> term().
+ +
+ +

Returns the value of a simple key/value property in json object Equivalent to get_value(Key, JsonObj, undefined).

+
+
+
+ +
+ + + +
+

get_value(Key, JsonObj, Default)

+ + + + + + +
+
+ +
+ +
+ +
-spec get_value(binary() | list(), doc(), term()) -> term().
+ +
+ +

Returns the value of a simple key/value property in json object function from erlang_couchdb

+
+
+
+ +
+ + + +
+

is_saved(Doc)

+ + + + + + +
+
+ +
+ +
+ +
-spec is_saved(doc()) -> boolean().
+ +
+ +

If document have been saved (revision is defined) return true, else, return false.

+
+
+
+ +
+ + + +
+

set_value(Key, Value, JsonObj)

+ + + + + + +
+
+ +
+ +
+ +
-spec set_value(binary() | list(), term(), doc()) -> doc().
+ +
+ +

set a value for a key in jsonobj. If key exists it will be updated.

+
+
+
+ +
+ + + +
+

take_value(Key, JsonObj)

+ + + + + + +
+
+ +
+ +
+ +
-spec take_value(binary() | list(), doc()) -> {term(), doc()}.
+ +
+ +

Returns the value of a simple key/value property in json object and deletes it form json object Equivalent to take_value(Key, JsonObj, undefined).

+
+
+
+ +
+ + + +
+

take_value(Key, JsonObj, Default)

+ + + + + + +
+
+ +
+ +
+ +
-spec take_value(binary() | list(), doc(), term()) -> {term(), doc()}.
+ +
+ +

Returns the value of a simple key/value property in json object and deletes it from json object

+
+
+ +
+
+ + +
+
+
+ + + diff --git a/site/couchbeam_ejson.html b/site/couchbeam_ejson.html new file mode 100644 index 00000000..799e4984 --- /dev/null +++ b/site/couchbeam_ejson.html @@ -0,0 +1,499 @@ + + + + + + + + + + + couchbeam_ejson — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + +
+
+

+ couchbeam_ejson + (couchbeam v2.0.0) + +

+ + + + View Source + + +
+ + +
+ +
+

+ + + + Summary +

+
+

+ Types +

+ +
+
+ ejson/0 + +
+ +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+
+ ejson_term/0 + +
+ +
+ +
+
+

+ Functions +

+ +
+
+ decode(D) + +
+ +

decode a binary to an EJSON term. Throw an exception if there is any error.

+ +
+ +
+
+ encode(D) + +
+ +

encode an erlang term to JSON. Throw an exception if there is any error.

+ +
+ +
+ + +
+ +
+ +
+ + +
+

+ + + + Types +

+
+
+ +
+ + + +
+

ejson/0

+ + + + + + +
+
+ +
+ +
+ +
-type ejson() :: ejson_object() | ejson_array().
+ +
+ + +
+
+
+ +
+ + + +
+

ejson_array/0

+ + + + + + +
+
+ +
+ +
+ +
-type ejson_array() :: [ejson_term()].
+ +
+ + +
+
+
+ +
+ + + +
+

ejson_number/0

+ + + + + + +
+
+ +
+ +
+ +
-type ejson_number() :: float() | integer().
+ +
+ + +
+
+
+ +
+ + + +
+

ejson_object/0

+ + + + + + +
+
+ +
+ +
+ +
-type ejson_object() :: map().
+ +
+ + +
+
+
+ +
+ + + +
+

ejson_string/0

+ + + + + + +
+
+ +
+ +
+ +
-type ejson_string() :: binary().
+ +
+ + +
+
+
+ +
+ + + +
+

ejson_term/0

+ + + + + + +
+
+ +
+ +
+ +
-type ejson_term() ::
+          ejson_array() | ejson_object() | ejson_string() | ejson_number() | true | false | null.
+ +
+ + +
+
+ +
+
+ +
+

+ + + + Functions +

+
+
+ +
+ + + +
+

decode(D)

+ + + + + + +
+
+ +
+ +
+ +
-spec decode(binary()) -> ejson().
+ +
+ +

decode a binary to an EJSON term. Throw an exception if there is any error.

+
+
+
+ +
+ + + +
+

encode(D)

+ + + + + + +
+
+ +
+ +
+ +
-spec encode(ejson()) -> binary().
+ +
+ +

encode an erlang term to JSON. Throw an exception if there is any error.

+
+
+
+ +
+ + + +
+

post_decode(Term)

+ + + + + + +
+
+ +
+ + +
+
+ +
+
+ + +
+
+
+ + + diff --git a/site/couchbeam_httpc.html b/site/couchbeam_httpc.html new file mode 100644 index 00000000..8c0a2e6b --- /dev/null +++ b/site/couchbeam_httpc.html @@ -0,0 +1,568 @@ + + + + + + + + + + + couchbeam_httpc — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + +
+
+

+ couchbeam_httpc + (couchbeam v2.0.0) + +

+ + + + View Source + + +
+ + +
+ +
+

+ + + + Summary +

+
+

+ Types +

+ +
+
+ db/0 + +
+ +
+ +
+
+ server/0 + +
+ +
+ +
+
+

+ Functions +

+ + + + + +
+ + +
+ +
+
+ db_url(Db) + +
+ +
+ +
+ + +
+ +
+ + +
+ + + + + + + +
+ + +

Asemble the server URL for the given client

+ +
+ +
+ +
+ + +
+

+ + + + Types +

+
+
+ +
+ + + +
+

db/0

+ + + + + + +
+
+ +
+ +
+ +
-type db() :: #db{server :: server(), name :: binary(), options :: list()}.
+ +
+ + +
+
+
+ +
+ + + +
+

server/0

+ + + + + + +
+
+ +
+ +
+ +
-type server() :: #server{url :: term(), options :: list()}.
+ +
+ + +
+
+ +
+
+ +
+

+ + + + Functions +

+
+
+ +
+ + + +
+

db_request(Method, Url, Headers, Body, Options)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

db_request(Method, Url, Headers, Body, Options, Expect)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

db_resp(Resp, Expect)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

db_url(Db)

+ + + + + + +
+
+ +
+ +
+ +
-spec db_url(db()) -> binary().
+ +
+ + +
+
+
+ +
+ + + +
+

doc_url(Db, DocId)

+ + + + + + +
+
+ +
+ +
+ +
-spec doc_url(db(), binary()) -> binary().
+ +
+ + +
+
+
+ +
+ + + +
+

json_body(Ref)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

make_headers(Method, Url, Headers, Options)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

maybe_oauth_header(Method, Url, Headers, Options)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

request(Method, Url, Headers, Body, Options)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

server_url(Server)

+ + + + + + +
+
+ +
+ +
+ +
-spec server_url(server()) -> binary().
+ +
+ +

Asemble the server URL for the given client

+
+
+ +
+
+ + +
+
+
+ + + diff --git a/site/couchbeam_sup.html b/site/couchbeam_sup.html new file mode 100644 index 00000000..bee7b056 --- /dev/null +++ b/site/couchbeam_sup.html @@ -0,0 +1,218 @@ + + + + + + + + + + + couchbeam_sup — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + +
+
+

+ couchbeam_sup + (couchbeam v2.0.0) + +

+ + + + View Source + + +
+ + +
+ +
+

+ + + + Summary +

+
+

+ Functions +

+ +
+
+ init(_) + +
+ +
+ +
+
+ start_link() + +
+ +
+ +
+ +
+ + +
+

+ + + + Functions +

+
+
+ +
+ + + +
+

init(_)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

start_link()

+ + + + + + +
+
+ +
+ + +
+
+ +
+
+ + +
+
+
+ + + diff --git a/site/couchbeam_util.html b/site/couchbeam_util.html new file mode 100644 index 00000000..712b29be --- /dev/null +++ b/site/couchbeam_util.html @@ -0,0 +1,972 @@ + + + + + + + + + + + couchbeam_util — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + +
+
+

+ couchbeam_util + (couchbeam v2.0.0) + +

+ + + + View Source + + +
+ + +
+ +
+

+ + + + Summary +

+
+

+ Functions +

+ + + +
+ + +
+ + + +
+ + +
+ +
+ + +
+ +
+ + +
+ + + +
+ + +

Encode needed query parameter values for JSON

+ +
+ +
+ + +

Encode value in JSON if needed depending on the key

+ +
+ +
+ + +

Replace a value in a property list

+ +
+ + + +
+ + +

Emulate proplists:get_value/2,3 for property lists but use faster lists:keyfind/3

+ +
+ + + + + +
+ + +

make view options a list

+ +
+ + + +
+ + +

Update a property list with values of the second. In case the same key is in both lists, the value from the first is kept.

+ +
+ +
+ + +

Merge two property lists (lists of {Key,Value}). All the Key - Value pairs from both lists are included in the new list. If a key occurs in both dictionaries then Fun is called with the key and both values to return a new value. This a wreapper around dict:merge

+ +
+ + + + + +
+ + +
+ +
+ + +

Start depedent applications of App.

+ +
+ +
+
+ to_atom(V) + +
+ +
+ +
+
+ to_binary(V) + +
+ +
+ +
+ + +
+ +
+
+ to_list(V) + +
+ +
+ +
+ +
+ + +
+

+ + + + Functions +

+
+
+ +
+ + + +
+

binary_env(Key, Default)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

dbname(DbName)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

deprecated(Old, New, When)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

encode_att_name(Name)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

encode_docid1(DocId)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

encode_docid(DocId)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

encode_docid_noop(DocId)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

encode_query(QSL)

+ + + + + + +
+
+ +
+ +

Encode needed query parameter values for JSON

+
+
+
+ +
+ + + +
+

encode_query_value(K, V)

+ + + + + + +
+
+ +
+ +

Encode value in JSON if needed depending on the key

+
+
+
+ +
+ + + +
+

force_param(Key, Value, Options)

+ + + + + + +
+
+ +
+ +

Replace a value in a property list

+
+
+
+ +
+ + + +
+

get_app_env(Env, Default)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

get_value(Key, Prop)

+ + + + + + +
+
+ +
+ +
+ +
-spec get_value(Key :: term(), Prop :: [term()]) -> term().
+ +
+ +

Emulate proplists:get_value/2,3 for property lists but use faster lists:keyfind/3

+
+
+
+ +
+ + + +
+

get_value(Key, Prop, Default)

+ + + + + + +
+
+ +
+ +
+ +
-spec get_value(Key :: term(), Prop :: [term()], Default :: term()) -> term().
+ +
+ + +
+
+
+ +
+ + + +
+

oauth_header(Url, Action, OauthProps)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

parse_options(Options)

+ + + + + + +
+
+ +
+ +

make view options a list

+
+
+
+ +
+ + + +
+

parse_options(Rest, Acc)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

propmerge1(L1, L2)

+ + + + + + +
+
+ +
+ +

Update a property list with values of the second. In case the same key is in both lists, the value from the first is kept.

+
+
+
+ +
+ + + +
+

propmerge(F, L1, L2)

+ + + + + + +
+
+ +
+ +

Merge two property lists (lists of {Key,Value}). All the Key - Value pairs from both lists are included in the new list. If a key occurs in both dictionaries then Fun is called with the key and both values to return a new value. This a wreapper around dict:merge

+
+
+
+ +
+ + + +
+

proxy_header(UserName, Roles, Secret)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

proxy_token(Secret, UserName)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

shutdown_sync(Pid)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

start_app_deps(App)

+ + + + + + +
+
+ +
+ +
+ +
-spec start_app_deps(atom()) -> ok.
+ +
+ +

Start depedent applications of App.

+
+
+
+ +
+ + + +
+

to_atom(V)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

to_binary(V)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

to_integer(V)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

to_list(V)

+ + + + + + +
+
+ +
+ + +
+
+ +
+
+ + +
+
+
+ + + diff --git a/site/couchbeam_uuids.html b/site/couchbeam_uuids.html new file mode 100644 index 00000000..64efa5e0 --- /dev/null +++ b/site/couchbeam_uuids.html @@ -0,0 +1,544 @@ + + + + + + + + + + + couchbeam_uuids — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + +
+
+

+ couchbeam_uuids + (couchbeam v2.0.0) + +

+ + + + View Source + + +
+ + +
+ +
+

+ + + + Summary +

+
+

+ Types +

+ +
+
+ server/0 + +
+ +
+ +
+
+

+ Functions +

+ + + +
+ + +

Get a list of uuids from the server

+ +
+ + + + + + + +
+
+ init(_) + +
+ +
+ +
+
+ random() + +
+ +

return a random uuid

+ +
+ +
+
+ start_link() + +
+ +

Starts the couchbeam process linked to the calling process. Usually invoked by the supervisor couchbeam_sup

+ +
+ + + +
+
+ utc_random() + +
+ +

return a random uuid based on time

+ +
+ +
+ +
+ + +
+

+ + + + Types +

+
+
+ +
+ + + +
+

server/0

+ + + + + + +
+
+ +
+ +
+ +
-type server() :: #server{url :: term(), options :: list()}.
+ +
+ + +
+
+ +
+
+ +
+

+ + + + Functions +

+
+
+ +
+ + + +
+

code_change(OldVsn, State, Extra)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

get_uuids(Server, Count)

+ + + + + + +
+
+ +
+ +
+ +
-spec get_uuids(server(), integer()) -> list().
+ +
+ +

Get a list of uuids from the server

+
+
+
+ +
+ + + +
+

handle_call(_, From, State)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

handle_cast(Msg, State)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

handle_info(Info, State)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

init(_)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

random()

+ + + + + + +
+
+ +
+ +
+ +
-spec random() -> binary().
+ +
+ +

return a random uuid

+
+
+
+ +
+ + + +
+

start_link()

+ + + + + + +
+
+ +
+ +
+ +
-spec start_link() -> {ok, pid()} | {error, term()}.
+ +
+ +

Starts the couchbeam process linked to the calling process. Usually invoked by the supervisor couchbeam_sup

+
+
+
+ +
+ + + +
+

terminate(Reason, State)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

utc_random()

+ + + + + + +
+
+ +
+ +
+ +
-spec utc_random() -> binary().
+ +
+ +

return a random uuid based on time

+
+
+ +
+
+ + +
+
+
+ + + diff --git a/site/couchbeam_view.html b/site/couchbeam_view.html new file mode 100644 index 00000000..474e0820 --- /dev/null +++ b/site/couchbeam_view.html @@ -0,0 +1,1508 @@ + + + + + + + + + + + couchbeam_view — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + +
+
+

+ couchbeam_view + (couchbeam v2.0.0) + +

+ + + + View Source + + +
+ + +
+ +
+

+ + + + Summary +

+
+

+ Types +

+ +
+
+ db/0 + +
+ +
+ +
+ + +
+ +
+ + +
+ +
+
+ server/0 + +
+ +
+ +
+ + +

example: "foo=bar&baz=biz"

+ +
+ +
+ + +
+ +
+
+ stale/0 + +
+ +
+ +
+
+ view_name/0 + +
+ +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+
+

+ Functions +

+ +
+
+ all(Db) + +
+ + + +
+ +
+ + + + +
+ +
+ + +
+ +
+
+ count(Db) + +
+ + + +
+ +
+ + + + +
+ +
+ + +

count number of doc in a view (or all docs)

+ +
+ +
+
+ fetch(Db) + +
+ + + +
+ +
+ + + + +
+ +
+ + +

Collect view results

+ +
+ +
+
+ first(Db) + +
+ +
+ +
+ + + + +
+ +
+ + +

get first result of a view

+ +
+ + + +
+ + +

call Function(Row, AccIn) on succesive row, starting with AccIn == Acc. Function/2 must return a new list accumultator or the atom done to stop fetching results. Acc0 is returned if the list is empty. For example

+ +
+ + + +
+ + +

call Function(Row) on succesive row. Example

+ +
+ +
+ + +

parse view options

+ +
+ +
+ + +
+ + + + + +
+ + + + +
+ +
+ + +

stream view results to a pid Db: a db record ViewName: 'all_docs' to get all docs or {DesignName, ViewName} Client receives messages: - {row, StartRef, done} All rows have been fetched - {row, StartRef, Row :: ejson_object()} A row in the view - {error, StartRef, Error} An error occurred; stream closed Options include (see couchbeam_view:parse_view_options/1): - {key, Key} - {start_docid, DocId} | {startkey_docid, DocId} - {end_docid, DocId} | {endkey_docid, DocId} - {start_key, Key} | {end_key, Key} - {limit, N} - {stale, ok | update_after | false} - descending | {skip, N} - group | {group_level, integer()} - reduce | {reduce, boolean()} - include_docs | conflicts | {inclusive_end, boolean()} - {keys, [Key]} - {stream_to, Pid}

+ +
+ +
+ + +
+ +
+ +
+ + +
+

+ + + + Types +

+
+
+ +
+ + + +
+

db/0

+ + + + + + +
+
+ +
+ +
+ +
-type db() :: #db{server :: server(), name :: binary(), options :: list()}.
+ +
+ + +
+
+
+ +
+ + + +
+

design_name/0

+ + + + + + +
+
+ +
+ +
+ +
-type design_name() :: binary() | string().
+ +
+ + +
+
+
+ +
+ + + +
+

ejson_object/0

+ + + + + + +
+
+ +
+ +
+ +
-type ejson_object() :: map().
+ +
+ + +
+
+
+ +
+ + + +
+

server/0

+ + + + + + +
+
+ +
+ +
+ +
-type server() :: #server{url :: term(), options :: list()}.
+ +
+ + +
+
+
+ +
+ + + +
+

show_option/0

+ + + + + + +
+
+ +
+ +
+ +
-type show_option() :: {query_string, binary()}.
+ +
+ +

example: "foo=bar&baz=biz"

+
+
+
+ +
+ + + +
+

show_options/0

+ + + + + + +
+
+ +
+ +
+ +
-type show_options() :: [show_option()].
+ +
+ + +
+
+
+ +
+ + + +
+

stale/0

+ + + + + + +
+
+ +
+ +
+ +
-type stale() :: ok | update_after | false.
+ +
+ + +
+
+
+ +
+ + + +
+

view_name/0

+ + + + + + +
+
+ +
+ +
+ +
-type view_name() :: binary() | string().
+ +
+ + +
+
+
+ +
+ + + +
+

view_option/0

+ + + + + + +
+
+ +
+ +
+ +
-type view_option() ::
+          {key, binary()} |
+          {startkey_docid, binary()} |
+          {start_docid, binary()} |
+          {startkey_docid, binary()} |
+          {end_docid, binary()} |
+          {endkey_docid, binary()} |
+          {start_key, binary()} |
+          {end_key, binary()} |
+          {limit, integer()} |
+          {stale, stale()} |
+          descending |
+          {skip, integer()} |
+          group |
+          {group_level, exact | integer()} |
+          reduce |
+          {reduce, boolean()} |
+          inclusive_end | include_docs | conflicts |
+          {list, binary()} |
+          {keys, [binary()]} |
+          async_query.
+ +
+ + +
+
+
+ +
+ + + +
+

view_options/0

+ + + + + + +
+
+ +
+ +
+ +
-type view_options() :: [view_option()].
+ +
+ + +
+
+
+ +
+ + + +
+

view_query_args/0

+ + + + + + +
+
+ +
+ +
+ +
-type view_query_args() ::
+          #view_query_args{method :: atom(), options :: view_options(), keys :: [binary()]}.
+ +
+ + +
+
+ +
+
+ +
+

+ + + + Functions +

+
+
+ +
+ + + +
+

all(Db)

+ + + + + + +
+
+ +
+ +
+ +
-spec all(Db :: db()) ->
+             {ok, Rows :: [ejson_object()]} |
+             {error, term()} |
+             {error, term(), Rows :: [ejson_object()]}.
+ +
+ +

Equivalent to fetch(Db, all_docs, []).

fetch all docs

+
+
+
+ +
+ + + +
+

all(Db, Options)

+ + + + + + +
+
+ +
+ +
+ +
-spec all(Db :: db(), Options :: view_options()) ->
+             {ok, Rows :: [ejson_object()]} |
+             {error, term()} |
+             {error, term(), Rows :: [ejson_object()]}.
+ +
+ +

Equivalent to fetch(Db, all_docs, Options).

fetch all docs

+
+
+
+ +
+ + + +
+

cancel_stream(Ref)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

count(Db)

+ + + + + + +
+
+ +
+ +
+ +
-spec count(Db :: db()) -> integer() | {error, term()}.
+ +
+ +

Equivalent to count(Db, all_docs, []).

+
+
+
+ +
+ + + +
+

count(Db, ViewName)

+ + + + + + +
+
+ +
+ +
+ +
-spec count(Db :: db(), ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()}) ->
+               integer() | {error, term()}.
+ +
+ +

Equivalent to count(Db, ViewName, []).

+
+
+
+ +
+ + + +
+

count(Db, ViewName, Options)

+ + + + + + +
+
+ +
+ +
+ +
-spec count(Db :: db(),
+            ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()},
+            Options :: view_options()) ->
+               integer() | {error, term()}.
+ +
+ +

count number of doc in a view (or all docs)

+
+
+
+ +
+ + + +
+

fetch(Db)

+ + + + + + +
+
+ +
+ +
+ +
-spec fetch(Db :: db()) ->
+               {ok, Rows :: [ejson_object()]} |
+               {error, term()} |
+               {error, term(), Rows :: [ejson_object()]}.
+ +
+ +

Equivalent to fetch(Db, all_docs, []).

+
+
+
+ +
+ + + +
+

fetch(Db, ViewName)

+ + + + + + +
+
+ +
+ +
+ +
-spec fetch(Db :: db(), ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()}) ->
+               {ok, Rows :: [ejson_object()]} | {error, term()}.
+ +
+ +

Equivalent to fetch(Db, ViewName, []).

+
+
+
+ +
+ + + +
+

fetch(Db, ViewName, Options)

+ + + + + + +
+
+ +
+ +
+ +
-spec fetch(Db :: db(),
+            ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()},
+            Options :: view_options()) ->
+               {ok, Rows :: [ejson_object()]} | {error, term()}.
+ +
+ +

Collect view results

Db: a db record

ViewName: 'all_docs' to get all docs or {DesignName, ViewName}

Options :: view_options() [{key, binary()}
+     | {start_docid, binary()} | {startkey_docid, binary()}
+     | {end_docid, binary()} | {endkey_docid, binary()}
+     | {start_key, binary()} | {end_key, binary()}
+     | {limit, integer()}
+     | {stale, stale()}
+     | descending
+     | {skip, integer()}
+     | group | {group_level, integer()}
+     | {inclusive_end, boolean()} | {reduce, boolean()} | reduce | include_docs | conflicts
+     | {keys, list(binary())}
+     | async_query

See couchbeam_view:stream/3 for more information about options.

Return: {ok, Rows} or {error, Error}

+
+
+
+ +
+ + + +
+

first(Db)

+ + + + + + +
+
+ +
+ +
+ +
-spec first(Db :: db()) -> {ok, Row :: ejson_object()} | {error, term()}.
+ +
+ + +
+
+
+ +
+ + + +
+

first(Db, ViewName)

+ + + + + + +
+
+ +
+ +
+ +
-spec first(Db :: db(), ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()}) ->
+               {ok, Row :: ejson_object()} | {error, term()}.
+ +
+ +

Equivalent to first(Db, ViewName, []).

+
+
+
+ +
+ + + +
+

first(Db, ViewName, Options)

+ + + + + + +
+
+ +
+ +
+ +
-spec first(Db :: db(),
+            ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()},
+            Options :: view_options()) ->
+               {ok, Rows :: ejson_object()} | {error, term()}.
+ +
+ +

get first result of a view

Db: a db record

ViewName: 'all_docs' to get all docs or {DesignName, ViewName}

Options :: view_options() [{key, binary()}
+     | {start_docid, binary()} | {startkey_docid, binary()}
+     | {end_docid, binary()} | {endkey_docid, binary()}
+     | {start_key, binary()} | {end_key, binary()}
+     | {limit, integer()}
+     | {stale, stale()}
+     | descending
+     | {skip, integer()}
+     | group | {group_level, integer()}
+     | {inclusive_end, boolean()} | {reduce, boolean()} | reduce | include_docs | conflicts
+     | {keys, list(binary())}

See couchbeam_view:stream/3 for more information about options.

Return: {ok, Row} or {error, Error}

+
+
+
+ +
+ + + +
+

fold(Function, Acc, Db, ViewName)

+ + + + + + +
+
+ +
+ +
+ +
-spec fold(Function :: function(),
+           Acc :: any(),
+           Db :: db(),
+           ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()}) ->
+              [term()] | {error, term()}.
+ +
+ +

Equivalent to fold(Function, Acc, Db, ViewName, []).

+
+
+
+ +
+ + + +
+

fold(Function, Acc, Db, ViewName, Options)

+ + + + + + +
+
+ +
+ +
+ +
-spec fold(Function :: function(),
+           Acc :: any(),
+           Db :: db(),
+           ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()},
+           Options :: view_options()) ->
+              [term()] | {error, term()}.
+ +
+ +

call Function(Row, AccIn) on succesive row, starting with AccIn == Acc. Function/2 must return a new list accumultator or the atom done to stop fetching results. Acc0 is returned if the list is empty. For example:

  couchbeam_view:fold(fun(Row, Acc) -> [Row|Acc] end, [], Db, 'all_docs').
+
+
+
+ +
+ + + +
+

foreach(Function, Db, ViewName)

+ + + + + + +
+
+ +
+ +
+ +
-spec foreach(Function :: function(),
+              Db :: db(),
+              ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()}) ->
+                 [term()] | {error, term()}.
+ +
+ +

Equivalent to foreach(Function, Db, ViewName, []).

+
+
+
+ +
+ + + +
+

foreach(Function, Db, ViewName, Options)

+ + + + + + +
+
+ +
+ +
+ +
-spec foreach(Function :: function(),
+              Db :: db(),
+              ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()},
+              Options :: view_options()) ->
+                 [term()] | {error, term()}.
+ +
+ +

call Function(Row) on succesive row. Example:

  couchbeam_view:foreach(fun(Row) -> io:format("got row ~p~n", [Row]) end, Db, 'all_docs').
+
+
+
+ +
+ + + +
+

parse_view_options(Options)

+ + + + + + +
+
+ +
+ +
+ +
-spec parse_view_options(Options :: list()) -> view_query_args().
+ +
+ +

parse view options

+
+
+
+ +
+ + + +
+

show(Db, ShowName)

+ + + + + + +
+
+ +
+ +
+ +
-spec show(db(), {binary(), binary()}) -> {ok, ejson_object()} | {error, term()}.
+ +
+ + +
+
+
+ +
+ + + +
+

show(Db, ShowName, DocId)

+ + + + + + +
+
+ +
+ +
+ +
-spec show(db(), {binary(), binary()}, binary()) -> {ok, ejson_object()} | {error, term()}.
+ +
+ + +
+
+
+ +
+ + + +
+

show(Db, _, DocId, Options)

+ + + + + + +
+
+ +
+ +
+ +
-spec show(db(), {binary(), binary()}, null | binary(), show_options()) ->
+              {ok, ejson_object()} | {error, term()}.
+ +
+ + +
+
+
+ +
+ + + +
+

stream(Db, ViewName)

+ + + + + + +
+
+ +
+ +
+ +
-spec stream(Db :: db(), ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()}) ->
+                {ok, StartRef :: term(), ViewPid :: pid()} | {error, term()}.
+ +
+ +

Equivalent to stream(Db, ViewName, []).

+
+
+
+ +
+ + + +
+

stream(Db, ViewName, Options)

+ + + + + + +
+
+ +
+ +
+ +
-spec stream(Db :: db(),
+             ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()},
+             Options :: view_options()) ->
+                {ok, StartRef :: term()} | {error, term()}.
+ +
+ +

stream view results to a pid Db: a db record ViewName: 'all_docs' to get all docs or {DesignName, ViewName} Client receives messages: - {row, StartRef, done} All rows have been fetched - {row, StartRef, Row :: ejson_object()} A row in the view - {error, StartRef, Error} An error occurred; stream closed Options include (see couchbeam_view:parse_view_options/1): - {key, Key} - {start_docid, DocId} | {startkey_docid, DocId} - {end_docid, DocId} | {endkey_docid, DocId} - {start_key, Key} | {end_key, Key} - {limit, N} - {stale, ok | update_after | false} - descending | {skip, N} - group | {group_level, integer()} - reduce | {reduce, boolean()} - include_docs | conflicts | {inclusive_end, boolean()} - {keys, [Key]} - {stream_to, Pid}

+
+
+
+ +
+ + + +
+

stream_next(Ref)

+ + + + + + +
+
+ +
+ + +
+
+ +
+
+ + +
+
+
+ + + diff --git a/site/couchbeam_view_stream.html b/site/couchbeam_view_stream.html new file mode 100644 index 00000000..8342df91 --- /dev/null +++ b/site/couchbeam_view_stream.html @@ -0,0 +1,344 @@ + + + + + + + + + + + couchbeam_view_stream — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + +
+
+

+ couchbeam_view_stream + (couchbeam v2.0.0) + +

+ + + + View Source + + +
+ + +
+ +
+

+ + + + Summary +

+ + +
+ + +
+

+ + + + Functions +

+
+
+ +
+ + + +
+

init_stream(Parent, Owner, StreamRef, Req, StreamOptions)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

maybe_continue(State)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

start_link(Owner, StreamRef, _, StreamOptions)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

system_code_change(Misc, _, _, _)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

system_continue(_, _, _)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

system_terminate(Reason, _, _, State)

+ + + + + + +
+
+ +
+ +
+ +
-spec system_terminate(any(), _, _, _) -> no_return().
+ +
+ + +
+
+ +
+
+ + +
+
+
+ + + diff --git a/site/couchbeam_view_sup.html b/site/couchbeam_view_sup.html new file mode 100644 index 00000000..fe1415e0 --- /dev/null +++ b/site/couchbeam_view_sup.html @@ -0,0 +1,224 @@ + + + + + + + + + + + couchbeam_view_sup — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + +
+
+

+ couchbeam_view_sup + (couchbeam v2.0.0) + +

+ + + + View Source + + +
+ + +
+ +
+

+ + + + Summary +

+
+

+ Functions +

+ +
+
+ init(_) + +
+ +
+ +
+
+ start_link() + +
+ +
+ +
+ +
+ + +
+

+ + + + Functions +

+
+
+ +
+ + + +
+

init(_)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

start_link()

+ + + + + + +
+
+ +
+ +
+ +
-spec start_link() -> {ok, pid()}.
+ +
+ + +
+
+ +
+
+ + +
+
+
+ + + diff --git a/site/dist/html-DPJLHKSM.js b/site/dist/html-DPJLHKSM.js new file mode 100644 index 00000000..8d3e3097 --- /dev/null +++ b/site/dist/html-DPJLHKSM.js @@ -0,0 +1,222 @@ +(()=>{var Ps=Object.create;var Kn=Object.defineProperty;var Os=Object.getOwnPropertyDescriptor;var Is=Object.getOwnPropertyNames;var As=Object.getPrototypeOf,Cs=Object.prototype.hasOwnProperty;var L=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var Rs=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Is(e))!Cs.call(t,i)&&i!==n&&Kn(t,i,{get:()=>e[i],enumerable:!(r=Os(e,i))||r.enumerable});return t};var Y=(t,e,n)=>(n=t!=null?Ps(As(t)):{},Rs(e||!t||!t.__esModule?Kn(n,"default",{value:t,enumerable:!0}):n,t));var wr=L((cc,yr)=>{var vr="Expected a function",mr=NaN,Bs="[object Symbol]",Qs=/^\s+|\s+$/g,qs=/^[-+]0x[0-9a-f]+$/i,Fs=/^0b[01]+$/i,Vs=/^0o[0-7]+$/i,$s=parseInt,Us=typeof global=="object"&&global&&global.Object===Object&&global,js=typeof self=="object"&&self&&self.Object===Object&&self,Ws=Us||js||Function("return this")(),zs=Object.prototype,Gs=zs.toString,Ks=Math.max,Ys=Math.min,Bt=function(){return Ws.Date.now()};function Js(t,e,n){var r,i,s,o,a,l,u=0,c=!1,d=!1,h=!0;if(typeof t!="function")throw new TypeError(vr);e=gr(e)||0,Fe(n)&&(c=!!n.leading,d="maxWait"in n,s=d?Ks(gr(n.maxWait)||0,e):s,h="trailing"in n?!!n.trailing:h);function p(S){var R=r,U=i;return r=i=void 0,u=S,o=t.apply(U,R),o}function g(S){return u=S,a=setTimeout(w,e),c?p(S):o}function m(S){var R=S-l,U=S-u,ee=e-R;return d?Ys(ee,s-U):ee}function v(S){var R=S-l,U=S-u;return l===void 0||R>=e||R<0||d&&U>=s}function w(){var S=Bt();if(v(S))return x(S);a=setTimeout(w,m(S))}function x(S){return a=void 0,h&&r?p(S):(r=i=void 0,o)}function P(){a!==void 0&&clearTimeout(a),u=0,r=l=i=a=void 0}function q(){return a===void 0?o:x(Bt())}function $(){var S=Bt(),R=v(S);if(r=arguments,i=this,l=S,R){if(a===void 0)return g(l);if(d)return a=setTimeout(w,e),p(l)}return a===void 0&&(a=setTimeout(w,e)),o}return $.cancel=P,$.flush=q,$}function Xs(t,e,n){var r=!0,i=!0;if(typeof t!="function")throw new TypeError(vr);return Fe(n)&&(r="leading"in n?!!n.leading:r,i="trailing"in n?!!n.trailing:i),Js(t,e,{leading:r,maxWait:e,trailing:i})}function Fe(t){var e=typeof t;return!!t&&(e=="object"||e=="function")}function Zs(t){return!!t&&typeof t=="object"}function eo(t){return typeof t=="symbol"||Zs(t)&&Gs.call(t)==Bs}function gr(t){if(typeof t=="number")return t;if(eo(t))return mr;if(Fe(t)){var e=typeof t.valueOf=="function"?t.valueOf():t;t=Fe(e)?e+"":e}if(typeof t!="string")return t===0?t:+t;t=t.replace(Qs,"");var n=Fs.test(t);return n||Vs.test(t)?$s(t.slice(2),n?2:8):qs.test(t)?mr:+t}yr.exports=Xs});var F=L(D=>{"use strict";D.__esModule=!0;D.extend=Cr;D.indexOf=po;D.escapeExpression=mo;D.isEmpty=go;D.createFrame=vo;D.blockParams=yo;D.appendContextPath=wo;var uo={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`","=":"="},co=/[&<>"'`=]/g,ho=/[&<>"'`=]/;function fo(t){return uo[t]}function Cr(t){for(var e=1;e{"use strict";je.__esModule=!0;var Kt=["description","fileName","lineNumber","endLineNumber","message","name","number","stack"];function Yt(t,e){var n=e&&e.loc,r=void 0,i=void 0,s=void 0,o=void 0;n&&(r=n.start.line,i=n.end.line,s=n.start.column,o=n.end.column,t+=" - "+r+":"+s);for(var a=Error.prototype.constructor.call(this,t),l=0;l{"use strict";We.__esModule=!0;var Jt=F();We.default=function(t){t.registerHelper("blockHelperMissing",function(e,n){var r=n.inverse,i=n.fn;if(e===!0)return i(this);if(e===!1||e==null)return r(this);if(Jt.isArray(e))return e.length>0?(n.ids&&(n.ids=[n.name]),t.helpers.each(e,n)):r(this);if(n.data&&n.ids){var s=Jt.createFrame(n.data);s.contextPath=Jt.appendContextPath(n.data.contextPath,n.name),n={data:s}}return i(e,n)})};Hr.exports=We.default});var Br=L((ze,Dr)=>{"use strict";ze.__esModule=!0;function bo(t){return t&&t.__esModule?t:{default:t}}var we=F(),Eo=X(),xo=bo(Eo);ze.default=function(t){t.registerHelper("each",function(e,n){if(!n)throw new xo.default("Must pass iterator to #each");var r=n.fn,i=n.inverse,s=0,o="",a=void 0,l=void 0;n.data&&n.ids&&(l=we.appendContextPath(n.data.contextPath,n.ids[0])+"."),we.isFunction(e)&&(e=e.call(this)),n.data&&(a=we.createFrame(n.data));function u(g,m,v){a&&(a.key=g,a.index=m,a.first=m===0,a.last=!!v,l&&(a.contextPath=l+g)),o=o+r(e[g],{data:a,blockParams:we.blockParams([e[g],g],[l+g,null])})}if(e&&typeof e=="object")if(we.isArray(e))for(var c=e.length;s{"use strict";Ge.__esModule=!0;function ko(t){return t&&t.__esModule?t:{default:t}}var So=X(),Lo=ko(So);Ge.default=function(t){t.registerHelper("helperMissing",function(){if(arguments.length!==1)throw new Lo.default('Missing helper: "'+arguments[arguments.length-1].name+'"')})};Qr.exports=Ge.default});var Ur=L((Ke,$r)=>{"use strict";Ke.__esModule=!0;function To(t){return t&&t.__esModule?t:{default:t}}var Fr=F(),_o=X(),Vr=To(_o);Ke.default=function(t){t.registerHelper("if",function(e,n){if(arguments.length!=2)throw new Vr.default("#if requires exactly one argument");return Fr.isFunction(e)&&(e=e.call(this)),!n.hash.includeZero&&!e||Fr.isEmpty(e)?n.inverse(this):n.fn(this)}),t.registerHelper("unless",function(e,n){if(arguments.length!=2)throw new Vr.default("#unless requires exactly one argument");return t.helpers.if.call(this,e,{fn:n.inverse,inverse:n.fn,hash:n.hash})})};$r.exports=Ke.default});var Wr=L((Ye,jr)=>{"use strict";Ye.__esModule=!0;Ye.default=function(t){t.registerHelper("log",function(){for(var e=[void 0],n=arguments[arguments.length-1],r=0;r{"use strict";Je.__esModule=!0;Je.default=function(t){t.registerHelper("lookup",function(e,n,r){return e&&r.lookupProperty(e,n)})};zr.exports=Je.default});var Yr=L((Xe,Kr)=>{"use strict";Xe.__esModule=!0;function Po(t){return t&&t.__esModule?t:{default:t}}var be=F(),Oo=X(),Io=Po(Oo);Xe.default=function(t){t.registerHelper("with",function(e,n){if(arguments.length!=2)throw new Io.default("#with requires exactly one argument");be.isFunction(e)&&(e=e.call(this));var r=n.fn;if(be.isEmpty(e))return n.inverse(this);var i=n.data;return n.data&&n.ids&&(i=be.createFrame(n.data),i.contextPath=be.appendContextPath(n.data.contextPath,n.ids[0])),r(e,{data:i,blockParams:be.blockParams([e],[i&&i.contextPath])})})};Kr.exports=Xe.default});var Xt=L(Ze=>{"use strict";Ze.__esModule=!0;Ze.registerDefaultHelpers=jo;Ze.moveHelperToHooks=Wo;function se(t){return t&&t.__esModule?t:{default:t}}var Ao=Nr(),Co=se(Ao),Ro=Br(),Mo=se(Ro),Ho=qr(),No=se(Ho),Do=Ur(),Bo=se(Do),Qo=Wr(),qo=se(Qo),Fo=Gr(),Vo=se(Fo),$o=Yr(),Uo=se($o);function jo(t){Co.default(t),Mo.default(t),No.default(t),Bo.default(t),qo.default(t),Vo.default(t),Uo.default(t)}function Wo(t,e,n){t.helpers[e]&&(t.hooks[e]=t.helpers[e],n||delete t.helpers[e])}});var Xr=L((et,Jr)=>{"use strict";et.__esModule=!0;var zo=F();et.default=function(t){t.registerDecorator("inline",function(e,n,r,i){var s=e;return n.partials||(n.partials={},s=function(o,a){var l=r.partials;r.partials=zo.extend({},l,n.partials);var u=e(o,a);return r.partials=l,u}),n.partials[i.args[0]]=i.fn,s})};Jr.exports=et.default});var Zr=L(Zt=>{"use strict";Zt.__esModule=!0;Zt.registerDefaultDecorators=Jo;function Go(t){return t&&t.__esModule?t:{default:t}}var Ko=Xr(),Yo=Go(Ko);function Jo(t){Yo.default(t)}});var en=L((tt,ei)=>{"use strict";tt.__esModule=!0;var Xo=F(),fe={methodMap:["debug","info","warn","error"],level:"info",lookupLevel:function(e){if(typeof e=="string"){var n=Xo.indexOf(fe.methodMap,e.toLowerCase());n>=0?e=n:e=parseInt(e,10)}return e},log:function(e){if(e=fe.lookupLevel(e),typeof console<"u"&&fe.lookupLevel(fe.level)<=e){var n=fe.methodMap[e];console[n]||(n="log");for(var r=arguments.length,i=Array(r>1?r-1:0),s=1;s{"use strict";tn.__esModule=!0;tn.createNewLookupObject=ea;var Zo=F();function ea(){for(var t=arguments.length,e=Array(t),n=0;n{"use strict";Ee.__esModule=!0;Ee.createProtoAccessControl=ia;Ee.resultIsAllowed=sa;Ee.resetLoggedProperties=aa;function ta(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e.default=t,e}var ni=ti(),na=en(),ra=ta(na),nt=Object.create(null);function ia(t){var e=Object.create(null);e.constructor=!1,e.__defineGetter__=!1,e.__defineSetter__=!1,e.__lookupGetter__=!1;var n=Object.create(null);return n.__proto__=!1,{properties:{whitelist:ni.createNewLookupObject(n,t.allowedProtoProperties),defaultValue:t.allowProtoPropertiesByDefault},methods:{whitelist:ni.createNewLookupObject(e,t.allowedProtoMethods),defaultValue:t.allowProtoMethodsByDefault}}}function sa(t,e,n){return ri(typeof t=="function"?e.methods:e.properties,n)}function ri(t,e){return t.whitelist[e]!==void 0?t.whitelist[e]===!0:t.defaultValue!==void 0?t.defaultValue:(oa(e),!1)}function oa(t){nt[t]!==!0&&(nt[t]=!0,ra.log("error",'Handlebars: Access has been denied to resolve the property "'+t+`" because it is not an "own property" of its parent. +You can add a runtime option to disable the check or this warning: +See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details`))}function aa(){Object.keys(nt).forEach(function(t){delete nt[t]})}});var an=L(j=>{"use strict";j.__esModule=!0;j.HandlebarsEnvironment=on;function ii(t){return t&&t.__esModule?t:{default:t}}var oe=F(),la=X(),rn=ii(la),ua=Xt(),ca=Zr(),da=en(),rt=ii(da),ha=nn(),fa="4.7.7";j.VERSION=fa;var pa=8;j.COMPILER_REVISION=pa;var ma=7;j.LAST_COMPATIBLE_COMPILER_REVISION=ma;var ga={1:"<= 1.0.rc.2",2:"== 1.0.0-rc.3",3:"== 1.0.0-rc.4",4:"== 1.x.x",5:"== 2.0.0-alpha.x",6:">= 2.0.0-beta.1",7:">= 4.0.0 <4.3.0",8:">= 4.3.0"};j.REVISION_CHANGES=ga;var sn="[object Object]";function on(t,e,n){this.helpers=t||{},this.partials=e||{},this.decorators=n||{},ua.registerDefaultHelpers(this),ca.registerDefaultDecorators(this)}on.prototype={constructor:on,logger:rt.default,log:rt.default.log,registerHelper:function(e,n){if(oe.toString.call(e)===sn){if(n)throw new rn.default("Arg not supported with multiple helpers");oe.extend(this.helpers,e)}else this.helpers[e]=n},unregisterHelper:function(e){delete this.helpers[e]},registerPartial:function(e,n){if(oe.toString.call(e)===sn)oe.extend(this.partials,e);else{if(typeof n>"u")throw new rn.default('Attempting to register a partial called "'+e+'" as undefined');this.partials[e]=n}},unregisterPartial:function(e){delete this.partials[e]},registerDecorator:function(e,n){if(oe.toString.call(e)===sn){if(n)throw new rn.default("Arg not supported with multiple decorators");oe.extend(this.decorators,e)}else this.decorators[e]=n},unregisterDecorator:function(e){delete this.decorators[e]},resetLoggedPropertyAccesses:function(){ha.resetLoggedProperties()}};var va=rt.default.log;j.log=va;j.createFrame=oe.createFrame;j.logger=rt.default});var oi=L((it,si)=>{"use strict";it.__esModule=!0;function ln(t){this.string=t}ln.prototype.toString=ln.prototype.toHTML=function(){return""+this.string};it.default=ln;si.exports=it.default});var ai=L(un=>{"use strict";un.__esModule=!0;un.wrapHelper=ya;function ya(t,e){if(typeof t!="function")return t;var n=function(){var i=arguments[arguments.length-1];return arguments[arguments.length-1]=e(i),t.apply(this,arguments)};return n}});var hi=L(Z=>{"use strict";Z.__esModule=!0;Z.checkRevision=Sa;Z.template=La;Z.wrapProgram=st;Z.resolvePartial=Ta;Z.invokePartial=_a;Z.noop=ci;function wa(t){return t&&t.__esModule?t:{default:t}}function ba(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e.default=t,e}var Ea=F(),z=ba(Ea),xa=X(),G=wa(xa),K=an(),li=Xt(),ka=ai(),ui=nn();function Sa(t){var e=t&&t[0]||1,n=K.COMPILER_REVISION;if(!(e>=K.LAST_COMPATIBLE_COMPILER_REVISION&&e<=K.COMPILER_REVISION))if(e{"use strict";ot.__esModule=!0;ot.default=function(t){var e=typeof global<"u"?global:window,n=e.Handlebars;t.noConflict=function(){return e.Handlebars===t&&(e.Handlebars=n),t}};fi.exports=ot.default});var ae=L((at,yi)=>{"use strict";at.__esModule=!0;function dn(t){return t&&t.__esModule?t:{default:t}}function hn(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e.default=t,e}var Aa=an(),mi=hn(Aa),Ca=oi(),Ra=dn(Ca),Ma=X(),Ha=dn(Ma),Na=F(),cn=hn(Na),Da=hi(),gi=hn(Da),Ba=pi(),Qa=dn(Ba);function vi(){var t=new mi.HandlebarsEnvironment;return cn.extend(t,mi),t.SafeString=Ra.default,t.Exception=Ha.default,t.Utils=cn,t.escapeExpression=cn.escapeExpression,t.VM=gi,t.template=function(e){return gi.template(e,t)},t}var xe=vi();xe.create=vi;Qa.default(xe);xe.default=xe;at.default=xe;yi.exports=at.default});var zi=L((ji,Wi)=>{(function(){var t=function(e){var n=new t.Builder;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),n.searchPipeline.add(t.stemmer),e.call(n,n),n.build()};t.version="2.3.9";t.utils={},t.utils.warn=function(e){return function(n){e.console&&console.warn&&console.warn(n)}}(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var n=Object.create(null),r=Object.keys(e),i=0;i0){var c=t.utils.clone(n)||{};c.position=[a,u],c.index=s.length,s.push(new t.Token(r.slice(a,o),c))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,n){n in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index. +`,e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(r){var i=t.Pipeline.registeredFunctions[r];if(i)n.add(i);else throw new Error("Cannot load unregistered function: "+r)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(n){t.Pipeline.warnIfFunctionNotRegistered(n),this._stack.push(n)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");r=r+1,this._stack.splice(r,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");this._stack.splice(r,0,n)},t.Pipeline.prototype.remove=function(e){var n=this._stack.indexOf(e);n!=-1&&this._stack.splice(n,1)},t.Pipeline.prototype.run=function(e){for(var n=this._stack.length,r=0;r1&&(oe&&(r=s),o!=e);)i=r-n,s=n+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(ol?c+=2:a==l&&(n+=r[u+1]*i[c+1],u+=2,c+=2);return n},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),n=1,r=0;n0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new t.TokenSet;s.node.edges["*"]=l}if(s.str.length==0&&(l.final=!0),i.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new t.TokenSet;s.node.edges["*"]=u}s.str.length==1&&(u.final=!0),i.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var c=s.str.charAt(0),d=s.str.charAt(1),h;d in s.node.edges?h=s.node.edges[d]:(h=new t.TokenSet,s.node.edges[d]=h),s.str.length==1&&(h.final=!0),i.push({node:h,editsRemaining:s.editsRemaining-1,str:c+s.str.slice(2)})}}}return r},t.TokenSet.fromString=function(e){for(var n=new t.TokenSet,r=n,i=0,s=e.length;i=e;n--){var r=this.uncheckedNodes[n],i=r.child.toString();i in this.minimizedNodes?r.parent.edges[r.char]=this.minimizedNodes[i]:(r.child._str=i,this.minimizedNodes[i]=r.child),this.uncheckedNodes.pop()}};t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(n){var r=new t.QueryParser(e,n);r.parse()})},t.Index.prototype.query=function(e){for(var n=new t.Query(this.fields),r=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),l=0;l1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,n){var r=e[this._ref],i=Object.keys(this._fields);this._documents[r]=n||{},this.documentCount+=1;for(var s=0;s=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,n;do e=this.next(),n=e.charCodeAt(0);while(n>47&&n<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var n=e.next();if(n==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(n.charCodeAt(0)==92){e.escapeCharacter();continue}if(n==":")return t.QueryLexer.lexField;if(n=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(n=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(n=="+"&&e.width()===1||n=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(n.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,n){this.lexer=new t.QueryLexer(e),this.query=n,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var n=e.peekLexeme();if(n!=null)switch(n.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expected either a field or a term, found "+n.type;throw n.str.length>=1&&(r+=" with value '"+n.str+"'"),new t.QueryParseError(r,n.start,n.end)}},t.QueryParser.parsePresence=function(e){var n=e.consumeLexeme();if(n!=null){switch(n.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var r="unrecognised presence operator'"+n.str+"'";throw new t.QueryParseError(r,n.start,n.end)}var i=e.peekLexeme();if(i==null){var r="expecting term or field, found nothing";throw new t.QueryParseError(r,n.start,n.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(r,i.start,i.end)}}},t.QueryParser.parseField=function(e){var n=e.consumeLexeme();if(n!=null){if(e.query.allFields.indexOf(n.str)==-1){var r=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+n.str+"', possible fields: "+r;throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.fields=[n.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,n.start,n.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var n=e.consumeLexeme();if(n!=null){e.currentClause.term=n.str.toLowerCase(),n.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var r=e.peekLexeme();if(r==null){e.nextClause();return}switch(r.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+r.type+"'";throw new t.QueryParseError(i,r.start,r.end)}}},t.QueryParser.parseEditDistance=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="edit distance must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.editDistance=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="boost must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.boost=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},function(e,n){typeof define=="function"&&define.amd?define(n):typeof ji=="object"?Wi.exports=n():e.lunr=n()}(this,function(){return t})})()});var Yn=new URLSearchParams(window.location.search),Jn=window.self!==window.parent,Pt=Jn&&Yn.has("preview"),Ot=Jn&&Yn.has("hint"),A=Pt||Ot;function Ae(){return window.sidebarNodes||{}}function Xn(){return window.versionNodes||[]}var f=document.querySelector.bind(document),M=document.querySelectorAll.bind(document);function Zn(t){return t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function Re(t){return String(t).replace(/&/g,"&").replace(//g,">").replace(/"/g,""")}function Me(){return document.getElementById("main").dataset.type}var Ce=["H1","H2","H3","H4","H5","H6"];function He(t=!1){let e=window.location.hash.replace(/^#/,"");if(!e)return t?document.getElementById("top-content"):null;let n=document.getElementById(e);if(!n)return null;if(n.matches(".detail"))return n;if(Ce.includes(n.tagName))return It(n);let r=Ms(n);return r||document.getElementById("top-content")}function Ms(t){let e=t.previousElementSibling;for(;e;){if(Ce.includes(e.tagName))return It(e);e=e.previousElementSibling}let n=t.parentNode;for(;n;){for(e=n.previousElementSibling;e;){if(Ce.includes(e.tagName))return It(e);e=e.previousElementSibling}n=n.parentNode}return null}function It(t){let e=document.createElement("div"),n=[t],r=t;for(;(r=r.nextSibling)&&!(Ce.includes(r.tagName)&&r.tagName<=t.tagName);)n.push(r);return e.append(...n),e}function er(t){return new URLSearchParams(window.location.search).get(t)}function At(t){return fetch(t).then(e=>e.ok).catch(()=>!1)}function he(t){return!t||t.trim()===""}function tr(t,e){let n;return function(...i){clearTimeout(n),n=setTimeout(()=>{n=null,t(...i)},e)}}function Ne(){return document.head.querySelector("meta[name=project][content]").content}function De(){return document.documentElement.classList.contains("apple-os")}function E(t,e,n){let r=document.createElement(t);for(let i in e)e[i]!=null&&r.setAttribute(i,e[i]);return n&&r.replaceChildren(...n),r}if(Pt&&A){let t=He(!0);if(t){document.body.classList.add("preview"),document.getElementById("content").replaceChildren(...t.childNodes);let e=document.getElementsByTagName("a:not([target=_blank]");for(let n of e)n.setAttribute("target","_parent");window.scrollTo(0,0),document.body.style.position="fixed",setTimeout(nr),window.addEventListener("resize",nr)}}function nr(){let t={type:"preview",contentHeight:document.getElementById("content").parentElement.offsetHeight};window.parent.postMessage(t,"*")}var ie={plain:"plain",function:"function",module:"module"},Hs=[{href:"typespecs.html#basic-types",hint:{kind:ie.plain,description:"Basic type"}},{href:"typespecs.html#literals",hint:{kind:ie.plain,description:"Literal"}},{href:"typespecs.html#built-in-types",hint:{kind:ie.plain,description:"Built-in type"}}],Be={cancelHintFetching:null};function rr(t){if(sr(t))return!0;let e=/#.*\//;return t.includes("#")&&!e.test(t)?!1:t.includes(".html")}function ir(t){let e=sr(t);return e?Promise.resolve(e):Ns(t)}function sr(t){let e=Hs.find(n=>t.includes(n.href));return e?e.hint:null}function Ns(t){let e=t.replace(".html",".html?hint=true");return new Promise((n,r)=>{let i=document.createElement("iframe");i.setAttribute("src",e),i.style.display="none";function s(a){let{href:l,hint:u}=a.data;e===l&&(o(),n(u))}Be.cancelHintFetching=()=>{o(),r(new Error("cancelled"))};function o(){i.remove(),window.removeEventListener("message",s),Be.cancelHintFetching=null}window.addEventListener("message",s),document.body.appendChild(i)})}function or(){Be.cancelHintFetching&&Be.cancelHintFetching()}function ar(t){let n=t.querySelector("h1").textContent,r=t.querySelector(".docstring > p"),i=r?r.innerHTML:"";return{kind:ie.function,title:n.trim(),description:i.trim()}}function lr(t){let n=t.querySelector("h1 > span").textContent,r=t.querySelector("#moduledoc p"),i=r?r.innerHTML:"";return{kind:ie.module,title:n.trim(),description:i.trim()}}if(Ot&&A){let t=He(),e=t?ar(t):["modules","tasks"].includes(Me())?lr(f(".content-inner")):null;if(e){let n={hint:{...e,version:Ne()},href:window.location.href};window.parent.postMessage(n,"*")}f(".content-inner")?.replaceChildren()}var Ct="ex_doc:settings",ur="dark",Rt="system",Mt="dark",Ht="light";var Ds={tooltips:!0,theme:null,livebookUrl:null},Nt=class{constructor(){this._subscribers=[],this._settings=Ds,this._loadSettings()}get(){return this._settings}update(e){let n=this._settings;this._settings={...this._settings,...e},this._subscribers.forEach(r=>r(this._settings,n)),this._storeSettings()}getAndSubscribe(e){this._subscribers.push(e),e(this._settings)}_loadSettings(){try{let e=localStorage.getItem(Ct);if(e){let n=JSON.parse(e);this._settings={...this._settings,...n}}this._loadSettingsLegacy()}catch(e){console.error(`Failed to load settings: ${e}`)}}_storeSettings(){try{this._storeSettingsLegacy(),localStorage.setItem(Ct,JSON.stringify(this._settings))}catch(e){console.error(`Failed to persist settings: ${e}`)}}_loadSettingsLegacy(){localStorage.getItem("tooltipsDisabled")!==null&&(this._settings={...this._settings,tooltips:!1}),localStorage.getItem("night-mode")==="true"&&(this._settings={...this._settings,nightMode:!0}),this._settings.nightMode===!0&&(this._settings={...this._settings,theme:"dark"})}_storeSettingsLegacy(){this._settings.tooltips?localStorage.removeItem("tooltipsDisabled"):localStorage.setItem("tooltipsDisabled","true"),this._settings.nightMode!==null?localStorage.setItem("night-mode",this._settings.nightMode===!0?"true":"false"):localStorage.removeItem("night-mode"),this._settings.theme!==null?(localStorage.setItem("night-mode",this._settings.theme==="dark"?"true":"false"),this._settings.nightMode=this._settings.theme==="dark"):(delete this._settings.nightMode,localStorage.removeItem("night-mode"))}},H=new Nt;var cr=!1,Qe=null,J=null;function dr(t){cr||(cr=!0,J=document.getElementById("toast"),J?.addEventListener("click",()=>{clearTimeout(Qe),J.classList.remove("show")})),J&&(clearTimeout(Qe),J.innerText=t,J.classList.add("show"),Qe=setTimeout(()=>{J.classList.remove("show"),Qe=setTimeout(function(){J.innerText=""},1e3)},5e3))}var Dt=[Rt,Mt,Ht],hr=window.matchMedia("(prefers-color-scheme: dark)");H.getAndSubscribe(fr);hr.addEventListener("change",fr);function fr(){let t=qe(),e=t===Mt||t!==Ht&&hr.matches;document.body.classList.toggle(ur,e)}function pr(){let t=Dt[Dt.indexOf(qe())+1]||Dt[0];H.update({theme:t}),dr(`Set theme to "${t}"`)}function qe(){return new URLSearchParams(window.location.search).get("theme")||H.get().theme||Rt}var _r=Y(wr());var Qt="sidebar_state",qt="closed",br="open",Er="sidebar_width";var Ve="sidebar-open",$e="sidebar-transition";var xr=!1;function kr(){if(xr)return;xr=!0;let t=document.getElementById("sidebar-list-nav");if(!t)return;let e=Me(),n={extras:t.dataset.extras||"Pages",modules:"Modules",tasks:'Mix Tasks'};Object.entries(n).forEach(([r,i])=>{let s=Ae()[r];if(!s?.length)return;let o=`${r}-list-tab-button`,a=`${r}-tab-panel`,l=r===e,u=E("button",{id:o,role:"tab",tabindex:l?0:-1,"aria-selected":l||void 0,"aria-controls":a});u.innerHTML=i,u.addEventListener("keydown",ro),u.addEventListener("click",io),t.appendChild(E("li",{},[u]));let c=E("ul",{class:"full-list"});c.addEventListener("click",so);let d=E("div",{id:a,class:"sidebar-tabpanel",role:"tabpanel","aria-labelledby":o,hidden:l?void 0:""},[c]);document.getElementById("sidebar").appendChild(d);let h="",p,g;c.replaceChildren(...s.flatMap(m=>{let v=[],w=Array.isArray(m.headers),x=w?void 0:"no",P=m?.url||`${m.id}.html`;return m.group!==h&&(v.push(E("li",{class:"group",translate:x},[m.group])),h=m.group,p=void 0),m.nested_context&&m.nested_context!==p?(p=m.nested_context,g!==p&&v.push(E("li",{class:"nesting-context",translate:"no","aria-hidden":!0},[p]))):g=m.title,v.push(E("li",{},[E("a",{href:P,translate:x},[m.nested_title||m.title,m.url?E("i",{class:"external-link ri-external-link-line"}):null].filter(Boolean)),...Vt(`node-${m.id}-headers`,w?to(m):no(m))])),v}))}),Ft(),requestAnimationFrame(Sr),window.addEventListener("hashchange",Ft),window.addEventListener("exdoc:loaded",Ft)}function Vt(t,e){return e.length?[E("button",{"aria-label":"expand","aria-expanded":!1,"aria-controls":t}),E("ul",{id:t},e)]:[]}function to(t){return t.headers.map(({id:e,anchor:n})=>E("li",{},[E("a",{href:`${t.id}.html#${n}`},[e])]))}function no(t){let e=[];return t.sections?.length&&e.push(E("li",{},[E("a",{href:`${t.id}.html#content`},["Sections"]),...Vt(`${t.id}-sections-list`,t.sections.map(({id:n,anchor:r})=>E("li",{},[E("a",{href:`${t.id}.html#${r}`},[n])])))])),t.nodeGroups&&(e.push(E("li",{},[E("a",{href:`${t.id}.html#summary`},["Summary"])])),e.push(...t.nodeGroups.map(({key:n,name:r,nodes:i})=>E("li",{},[E("a",{href:`${t.id}.html#${n}`},[r]),...Vt(`node-${t.id}-group-${n}-list`,i.map(({anchor:s,title:o,id:a})=>E("li",{},[E("a",{href:`${t.id}.html#${s}`,title:o,translate:"no"},[a])])))])))),e}function $t(t){let e=document.getElementById("sidebar-list-nav").querySelector("[aria-selected]");e!==t&&(e&&(e.removeAttribute("aria-selected"),e.setAttribute("tabindex","-1"),document.getElementById(e.getAttribute("aria-controls")).setAttribute("hidden","hidden")),t.setAttribute("aria-selected","true"),t.setAttribute("tabindex","0"),document.getElementById(t.getAttribute("aria-controls")).removeAttribute("hidden"))}function Sr(){f("#sidebar [role=tabpanel]:not([hidden]) a[aria-selected]")?.scrollIntoView()}function Ft(){let t=document.getElementById("sidebar"),{pathname:e,hash:n}=window.location,r=e.split("/").pop().replace(/\.html$/,"")+".html",i=t.querySelector(`li a[href="${r+n}"]`)||t.querySelector(`li a[href="${r}"]`);if(!i)return;t.querySelectorAll(".full-list a[aria-selected]").forEach(o=>{o.removeAttribute("aria-selected")}),t.querySelectorAll(".full-list button[aria-expanded=true]").forEach(o=>{o.setAttribute("aria-expanded",!1)});let s=i.parentElement;for(;s;){if(s.tagName==="LI"){let o=s.firstChild;o.setAttribute("aria-selected",o.getAttribute("href")===r?"page":"true");let a=o.nextSibling;a?.tagName==="BUTTON"&&a.setAttribute("aria-expanded",!0)}else if(s.role==="tabpanel"){s.hasAttribute("hidden")&&$t(document.getElementById(s.getAttribute("aria-labelledby")));break}s=s.parentElement}}function ro(t){if(!["ArrowRight","ArrowLeft"].includes(t.key))return;let e=Array.from(M('#sidebar-list-nav [role="tab"]')),r=e.indexOf(t.currentTarget)+(t.key==="ArrowRight"?1:-1),i=e.at(r%e.length);$t(i),i.focus()}function io(t){$t(t.currentTarget),Sr()}function so(t){let e=t.target;e.tagName==="BUTTON"&&e.setAttribute("aria-expanded",e.getAttribute("aria-expanded")==="false")}var ao=300,Pr=".sidebar-toggle",Ut=window.matchMedia(`screen and (max-width: ${768}px)`);if(!A){window.addEventListener("exdoc:loaded",Lr);let t=document.getElementById("sidebar"),e=f(Pr);e.addEventListener("click",Ue),document.body.addEventListener("click",i=>{Ut.matches&&jt()&&!t.contains(i.target)&&!e.contains(i.target)&&Ue()});let n=window.innerWidth;window.addEventListener("resize",(0,_r.default)(()=>{n!==window.innerWidth&&(n=window.innerWidth,Lr())},100));let r=new ResizeObserver(([i])=>{if(!i)return;let s=i.contentRect.width;sessionStorage.setItem(Er,s),document.body.style.setProperty("--sidebarWidth",`${s}px`)});t.addEventListener("mousedown",()=>r.observe(t)),t.addEventListener("mouseup",()=>r.unobserve(t)),window.addEventListener("hashchange",lo)}function Lr(){let e=sessionStorage.getItem(Qt)!==qt&&!Ut.matches;Ir(e)}function Ue(){let t=!jt();return sessionStorage.setItem(Qt,t?br:qt),Wt(t)}function jt(){return document.body.classList.contains(Ve)}function Or(){return document.body.classList.contains(Ve)&&!document.body.classList.contains($e)}function Ir(t){t&&kr(),document.body.classList.toggle(Ve,t),f(Pr).setAttribute("aria-expanded",t?"true":"false")}var Tr;function Wt(t){return new Promise(e=>{document.body.classList.add($e),document.body.scrollTop,Ir(t),clearTimeout(Tr),Tr=setTimeout(()=>{document.body.classList.remove($e),e()},ao)})}function Ar(){return Wt(!0)}function lo(){Ut.matches&&jt()&&Wt(!1)}var wi=Y(ae());var fn=Y(ae());fn.registerHelper("isArray",function(t,e){return Array.isArray(t)?e.fn(this):e.inverse(this)});fn.registerHelper("isNonEmptyArray",function(t,e){return Array.isArray(t)&&t.length>0?e.fn(this):e.inverse(this)});var bi=wi.template({1:function(t,e,n,r,i){var s,o,a=e??(t.nullContext||{}),l=t.hooks.helperMissing,u="function",c=t.escapeExpression,d=t.lookupProperty||function(h,p){if(Object.prototype.hasOwnProperty.call(h,p))return h[p]};return' +`},2:function(t,e,n,r,i){return" selected disabled"},4:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return` +`},compiler:[8,">= 4.3.0"],main:function(t,e,n,r,i){var s,o=e??(t.nullContext||{}),a=t.lookupProperty||function(l,u){if(Object.prototype.hasOwnProperty.call(l,u))return l[u]};return`
+ +`+((s=a(n,"if").call(o,e!=null?a(e,"latestVersion"):e,{name:"if",hash:{},fn:t.program(4,i,0),inverse:t.noop,data:i,loc:{start:{line:13,column:2},end:{line:19,column:9}}}))!=null?s:"")+`
+`},useData:!0});var qa=".sidebar-projectVersion",Ei=".sidebar-projectVersion select",Fa=".sidebar-staleVersion a";if(!A){let t=Xn(),e=f(qa);if(t.length>0||!e){let n=e.textContent.trim(),i=(t.some(u=>u.version===n)?t:[{version:n,url:"#"},...t]).map(u=>({...u,isCurrentVersion:u.version===n})),s=t.find(u=>u.latest),o=s?.version!==n&&!n.includes("-")?s?.url:null;e.innerHTML=bi({nodes:i,latestVersion:o});let a=f(Ei);a.addEventListener("change",$a),Va(a);let l=f(Fa);l&&l.addEventListener("click",Ua)}}function Va(t){let e=document.createElement("span");e.style.visibility="hidden",e.style.position="absolute",e.style.whiteSpace="nowrap",e.style.font=window.getComputedStyle(t).font,e.textContent=t.options[t.selectedIndex].text,document.body.appendChild(e),t.style.width=`${e.offsetWidth+20}px`,document.body.removeChild(e)}function $a(t){let e=t.target.value,n=window.location.pathname.split("/").pop()+window.location.hash,r=`${e}/${n}`;At(r).then(i=>{i?window.location.href=r:window.location.href=e})}function Ua(t){let e=this.href,n=window.location.pathname.split("/").pop()+window.location.hash,r=`${e}/${n}`;t.preventDefault(),At(r).then(i=>{i?window.location.href=r:window.location.href=e})}function pn(){let t=f(Ei);t&&(t.focus(),t.addEventListener("keydown",e=>{(e.key==="Escape"||e.key==="v")&&(e.preventDefault(),t.blur())}),navigator.userActivation.isActive&&"showPicker"in HTMLSelectElement.prototype&&t.showPicker())}var ja="content",Wa="tabs-open",za="tabs-close",Ga="H3",Ka="tabset";window.addEventListener("exdoc:loaded",Ya);function Ya(){let t=[],e=[],n=document.createNodeIterator(document.getElementById(ja),NodeFilter.SHOW_COMMENT,i=>i.nodeValue.trim()===Wa?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT),r;for(;r=n.nextNode();){let i=[];t.push([r,i]);let s,o=r;for(;o=o.nextSibling;)if(o.nodeName===Ga){s=[];let a=o.querySelector(".text")?.childNodes||o.childNodes;i.push([a,s]),e.push(o)}else if(o.nodeName==="#comment"&&o.nodeValue.trim()===za){e.push(o);break}else s&&s.push(o)}t.forEach(([i,s],o)=>{let a=E("div",{class:Ka});i.parentNode.replaceChild(a,i);let l=E("div",{role:"tablist",class:"tabset-tablist"});a.appendChild(l),s.forEach(([u,c],d)=>{let h=d===0,p=`tab-${o}-${d}`,g=`tabpanel-${o}-${d}`,m=E("button",{role:"tab",id:p,class:"tabset-tab",tabindex:h?0:-1,"aria-selected":h,"aria-controls":g},u);m.addEventListener("click",Ja),m.addEventListener("keydown",Xa),l.appendChild(m);let v=E("div",{role:"tabpanel",id:g,class:"tabset-panel",hidden:h?void 0:"",tabindex:h?0:-1,"aria-labelledby":p},c);a.appendChild(v)})}),e.forEach(i=>{i.parentNode.removeChild(i)})}function Ja(t){ki(t.currentTarget)}function Xa(t){if(xi[t.code]){t.preventDefault();let e=[...t.currentTarget.parentNode.childNodes],n=e.indexOf(t.currentTarget),r=xi[t.code](n,e.length);ki(e.at(r%e.length))}}var xi={ArrowLeft:t=>t-1,ArrowRight:t=>t+1,Home:()=>0,End:(t,e)=>e-1};function ki(t){let e=t.parentNode.querySelector("[aria-selected=true]");if(e===t)return;e.setAttribute("aria-selected","false"),e.tabIndex=-1,t.setAttribute("aria-selected","true"),t.tabIndex=0,t.focus();let n=document.getElementById(e.getAttribute("aria-controls"));n.setAttribute("hidden",""),n.tabIndex=-1;let r=document.getElementById(t.getAttribute("aria-controls"));r.removeAttribute("hidden"),r.tabIndex=0}window.addEventListener("exdoc:loaded",Za);function Za(){let t=window.location.pathname.replace(/(\.html)?$/,".livemd"),e=encodeURIComponent(new URL(t,window.location.href).toString());H.getAndSubscribe(({livebookUrl:n})=>{let r=n?`${n}/import?url=${e}`:`https://livebook.dev/run?url=${e}`;for(let i of M(".livebook-badge"))i.href=r})}var el="hll";window.addEventListener("exdoc:loaded",tl);function tl(){M("[data-group-id]").forEach(t=>{t.addEventListener("mouseenter",Si),t.addEventListener("mouseleave",Si)})}function Si(t){let e=t.currentTarget,n=t.type==="mouseenter",r=e.getAttribute("data-group-id");e.parentElement.querySelectorAll(`[data-group-id="${r}"]`).forEach(i=>{i.classList.toggle(el,n)})}var W={module:"module",moduleChild:"module-child",mixTask:"mix-task",extra:"extra",section:"section"};function Ti(t,e=8){if(he(t))return[];let n=Ae(),r=[...mn(n.modules,t,W.module,"module"),...nl(n.modules,t,W.moduleChild),...mn(n.tasks,t,W.mixTask,"mix task"),...mn(n.extras,t,W.extra,"page"),...gn(n.modules,t,W.section,"module"),...gn(n.tasks,t,W.section,"mix task"),...gn(n.extras,t,W.section,"page")].filter(i=>i!==null);return ul(r).slice(0,e)}function mn(t,e,n,r){return t.map(i=>i.searchData?null:il(i,e,n,r))}function nl(t,e,n){return t.filter(r=>r.nodeGroups).flatMap(r=>r.nodeGroups.flatMap(({key:i,nodes:s})=>{let o=ll(i);return s.map(a=>sl(a,r.id,e,n,o)||al(a,r.id,e,n,o))}))}function gn(t,e,n,r){return t.flatMap(i=>rl(i).map(s=>ol(i,s,e,n,r)))}function rl(t){return t.searchData?t.searchData:(t.sections||[]).concat(t.headers||[])}function il(t,e,n,r){return ut(t.title,e)?{link:`${t.id}.html`,title:ht(t.title,e),description:null,matchQuality:ct(t.title,e),deprecated:t.deprecated,labels:[r],category:n}:null}function sl(t,e,n,r,i){return ut(t.id,n)?{link:`${e}.html#${t.anchor}`,title:ht(t.id,n),labels:[i],description:e,matchQuality:ct(t.id,n),deprecated:t.deprecated,category:r}:null}function ol(t,e,n,r,i){if(!_i(e.id,n))return null;let s;return e.anchor===""?s=`${t.id}.html`:s=`${t.id}.html#${e.anchor}`,{link:s,title:ht(e.id,n),description:t.title,matchQuality:ct(e.id,n),labels:e.labels||[i,"section"],category:r}}function al(t,e,n,r,i){let s=`${e}.${t.id}`,o=`${e}:${t.id}`,a,l;if(ut(s,n))a=s,l=/\./g;else if(ut(o,n))a=o,l=/:/g;else return null;let u=n.replace(l," ");return _i(t.id,u)?{link:`${e}.html#${t.anchor}`,title:ht(t.id,u),label:i,description:e,matchQuality:ct(a,n),deprecated:t.deprecated,category:r}:null}function ll(t){switch(t){case"callbacks":return"callback";case"types":return"type";default:return"function"}}function ul(t){return t.slice().sort((e,n)=>e.matchQuality!==n.matchQuality?n.matchQuality-e.matchQuality:Li(e.category)-Li(n.category))}function Li(t){switch(t){case W.module:return 1;case W.moduleChild:return 2;case W.mixTask:return 3;default:return 4}}function _i(t,e){return dt(e).some(r=>Pi(t,r))}function ut(t,e){return dt(e).every(r=>Pi(t,r))}function Pi(t,e){return t.toLowerCase().includes(e.toLowerCase())}function ct(t,e){let n=dt(e),i=n.map(o=>o.length).reduce((o,a)=>o+a,0)/t.length,s=cl(t,n[0])?1:0;return i+s}function cl(t,e){return t.toLowerCase().startsWith(e.toLowerCase())}function dt(t){return t.trim().split(/\s+/)}function ht(t,e){let n=dt(e).sort((r,i)=>i.length-r.length);return lt(t,n)}function lt(t,e){if(e.length===0)return t;let[n,...r]=e,i=t.match(new RegExp(`(.*)(${Zn(n)})(.*)`,"i"));if(i){let[,s,o,a]=i;return lt(s,e)+""+Re(o)+""+lt(a,e)}else return lt(t,r)}var Oi=Y(ae());var Ii=Oi.template({1:function(t,e,n,r,i){var s,o,a=e??(t.nullContext||{}),l=t.hooks.helperMissing,u="function",c=t.escapeExpression,d=t.lookupProperty||function(h,p){if(Object.prototype.hasOwnProperty.call(h,p))return h[p]};return' +
+`+((s=d(n,"if").call(a,e!=null?d(e,"deprecated"):e,{name:"if",hash:{},fn:t.program(2,i,0),inverse:t.program(4,i,0),data:i,loc:{start:{line:16,column:10},end:{line:20,column:17}}}))!=null?s:"")+` +`+((s=d(n,"each").call(a,e!=null?d(e,"labels"):e,{name:"each",hash:{},fn:t.program(6,i,0),inverse:t.noop,data:i,loc:{start:{line:22,column:10},end:{line:24,column:19}}}))!=null?s:"")+`
+ +
+
+ +
+
+ +`+((s=d(n,"if").call(a,e!=null?d(e,"description"):e,{name:"if",hash:{},fn:t.program(8,i,0),inverse:t.noop,data:i,loc:{start:{line:39,column:8},end:{line:43,column:15}}}))!=null?s:"")+`
+`},2:function(t,e,n,r,i){var s,o,a=t.lookupProperty||function(l,u){if(Object.prototype.hasOwnProperty.call(l,u))return l[u]};return' '+((s=(o=(o=a(n,"title")||(e!=null?a(e,"title"):e))!=null?o:t.hooks.helperMissing,typeof o=="function"?o.call(e??(t.nullContext||{}),{name:"title",hash:{},data:i,loc:{start:{line:17,column:49},end:{line:17,column:60}}}):o))!=null?s:"")+` +`},4:function(t,e,n,r,i){var s,o,a=t.lookupProperty||function(l,u){if(Object.prototype.hasOwnProperty.call(l,u))return l[u]};return' '+((s=(o=(o=a(n,"title")||(e!=null?a(e,"title"):e))!=null?o:t.hooks.helperMissing,typeof o=="function"?o.call(e??(t.nullContext||{}),{name:"title",hash:{},data:i,loc:{start:{line:19,column:46},end:{line:19,column:57}}}):o))!=null?s:"")+` +`},6:function(t,e,n,r,i){return' '+t.escapeExpression(t.lambda(e,e))+` +`},8:function(t,e,n,r,i){var s,o,a=t.lookupProperty||function(l,u){if(Object.prototype.hasOwnProperty.call(l,u))return l[u]};return`
+ `+((s=(o=(o=a(n,"description")||(e!=null?a(e,"description"):e))!=null?o:t.hooks.helperMissing,typeof o=="function"?o.call(e??(t.nullContext||{}),{name:"description",hash:{},data:i,loc:{start:{line:41,column:10},end:{line:41,column:27}}}):o))!=null?s:"")+` +
+`},compiler:[8,">= 4.3.0"],main:function(t,e,n,r,i){var s,o,a=e??(t.nullContext||{}),l=t.lookupProperty||function(u,c){if(Object.prototype.hasOwnProperty.call(u,c))return u[c]};return`
+
+
+
+ + Autocompletion results for "`+t.escapeExpression((o=(o=l(n,"term")||(e!=null?l(e,"term"):e))!=null?o:t.hooks.helperMissing,typeof o=="function"?o.call(a,{name:"term",hash:{},data:i,loc:{start:{line:6,column:55},end:{line:6,column:63}}}):o))+`" + + + Press RETURN for full-text search, TAB for previews + +
+
+`+((s=l(n,"each").call(a,e!=null?l(e,"suggestions"):e,{name:"each",hash:{},fn:t.program(1,i,0),inverse:t.noop,data:i,loc:{start:{line:13,column:6},end:{line:45,column:15}}}))!=null?s:"")+`
+
+
+`},useData:!0});var pe=".autocomplete",pt=".autocomplete-suggestions",ft=".autocomplete-suggestion",C={autocompleteSuggestions:[],previewOpen:!1,selectedIdx:-1};function dl(){f(pe).classList.add("shown")}function vn(){f(pe).classList.remove("shown")}function Ai(){return f(pe).classList.contains("shown")}function yn(t){C.autocompleteSuggestions=Ti(t),C.selectedIdx=-1,he(t)?vn():(hl({term:t,suggestions:C.autocompleteSuggestions}),mt(0),dl())}function hl({term:t,suggestions:e}){let n=Ii({suggestions:e,term:t}),r=f(pe);r.innerHTML=n}function wn(){return C.selectedIdx===-1?null:C.autocompleteSuggestions[C.selectedIdx]}function mt(t){Ri(fl(t))}function Ci(t){if(t.data.type==="preview"){let{contentHeight:e}=t.data,n=f(".autocomplete-preview");n&&(n.style.height=`${e+32}px`,n.classList.remove("loading"))}}function Ri(t){C.selectedIdx=t;let e=f(pt),n=f(`${ft}.selected`),r=f(`${ft}[data-index="${C.selectedIdx}"]`);if(n&&n.classList.remove("selected"),r){if(C.previewOpen){Hi(),window.addEventListener("message",Ci),e.classList.add("previewing");let i=document.createElement("div");i.classList.add("autocomplete-preview"),i.classList.add("loading");let s=r.href.replace(".html",`.html?preview=true&theme=${qe()}`),o=document.createElement("iframe");o.setAttribute("src",s),i.appendChild(document.createElement("div")),i.appendChild(document.createElement("span")),i.appendChild(o),r.parentNode.insertBefore(i,r.nextSibling)}r.classList.add("selected"),r.scrollIntoView({block:"nearest"})}else e&&(e.scrollTop=0)}function Mi(){C.previewOpen?gt():bn()}function gt(){C.previewOpen=!1;let t=f(pt);t&&t.classList.remove("previewing"),Hi()}function bn(t){C.previewOpen=!0,t?t=t.closest(ft):t=f(`${ft}[data-index="${C.selectedIdx}"]`),t&&Ri(parseInt(t.dataset.index))}function Hi(){let t=f(".autocomplete-preview");t&&(t.remove(),window.removeEventListener("message",Ci))}function fl(t){let e=C.autocompleteSuggestions.length+1;return(C.selectedIdx+t+1+e)%e-1}var ke="form.search-bar input",pl="form.search-bar .search-close-button";A||window.addEventListener("exdoc:loaded",ml);function ml(){gl(),window.onTogglePreviewClick=function(t,e){t.preventDefault(),t.stopImmediatePropagation(),xn(),e?bn(t.target):gt()}}function Bi(t){let e=f(ke);e.value=t}function xn(){let t=f(ke);document.body.classList.add("search-focused"),t.focus()}function gl(){let t=f(ke);if(document.querySelector('meta[name="exdoc:autocomplete"][content="off"]'))return t.addEventListener("keydown",e=>{e.key==="Enter"&&Ni(e)}),!0;t.addEventListener("keydown",e=>{let n=De();e.key==="Escape"?(vt(),t.blur()):e.key==="Enter"?Ni(e):e.key==="ArrowUp"||n&&e.ctrlKey&&e.key==="p"?(mt(-1),e.preventDefault()):e.key==="ArrowDown"||n&&e.ctrlKey&&e.key==="n"?(mt(1),e.preventDefault()):e.key==="Tab"&&wn()!==null&&(Mi(),e.preventDefault())}),t.addEventListener("input",e=>{yn(e.target.value)}),t.addEventListener("focus",e=>{document.body.classList.contains("search-focused")||(document.body.classList.add("search-focused"),yn(e.target.value))}),t.addEventListener("blur",e=>{let n=e.relatedTarget,r=f(pt);if(n&&r&&r.contains(n))return setTimeout(()=>{Ai()&&t.focus()},1e3),null;yt()}),f(pe).addEventListener("click",e=>{e.shiftKey||e.ctrlKey?t.focus():(vt(),yt())}),f(pl).addEventListener("click",e=>{vt(),yt()})}function Ni(t){let e=f(ke),n=t.shiftKey||t.ctrlKey,r=wn();t.preventDefault();let i=n?"_blank":"_self",s=document.createElement("a");if(s.setAttribute("target",i),r)s.setAttribute("href",r.link);else{let o=document.querySelector('meta[name="exdoc:full-text-search-url"]'),a=o?o.getAttribute("content"):"search.html?q=";s.setAttribute("href",`${a}${encodeURIComponent(e.value)}`)}s.click(),n||(vt(),yt())}function vt(){let t=f(ke);t.value=""}function yt(){gt(),document.body.classList.remove("search-focused"),vn()}var En,Di=2;window.addEventListener("scroll",function(){let t=window.scrollY;if(En!==void 0){let e=t-En;t===0||e>Di?document.body.classList.remove("scroll-sticky"):t>0&&-e>Di&&document.body.classList.add("scroll-sticky")}En=Math.max(0,t)},!1);var Qi=Y(ae());var qi=Qi.template({1:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return`
+ `+t.escapeExpression(t.lambda((s=e!=null?o(e,"hint"):e)!=null?o(s,"description"):s,e))+` +
+`},3:function(t,e,n,r,i){var s,o=t.lambda,a=t.escapeExpression,l=t.lookupProperty||function(u,c){if(Object.prototype.hasOwnProperty.call(u,c))return u[c]};return`
+

+ `+a(o((s=e!=null?l(e,"hint"):e)!=null?l(s,"title"):s,e))+` +
`+a(o((s=e!=null?l(e,"hint"):e)!=null?l(s,"version"):s,e))+`
+

+
+`+((s=l(n,"if").call(e??(t.nullContext||{}),(s=e!=null?l(e,"hint"):e)!=null?l(s,"description"):s,{name:"if",hash:{},fn:t.program(4,i,0),inverse:t.noop,data:i,loc:{start:{line:12,column:2},end:{line:16,column:9}}}))!=null?s:"")},4:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return`
+ `+((s=t.lambda((s=e!=null?o(e,"hint"):e)!=null?o(s,"description"):s,e))!=null?s:"")+` +
+`},compiler:[8,">= 4.3.0"],main:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return(s=o(n,"if").call(e??(t.nullContext||{}),e!=null?o(e,"isPlain"):e,{name:"if",hash:{},fn:t.program(1,i,0),inverse:t.program(3,i,0),data:i,loc:{start:{line:1,column:0},end:{line:17,column:7}}}))!=null?s:""},useData:!0});var vl='
',yl='.content a:not([data-no-tooltip=""])',kn=".tooltip",Fi=".tooltip .tooltip-body",Vi="body .content-inner",wl="#content",$i="tooltip-shown",Se=10,bl=Se*4,El=768,xl=450,kl=100,le={currentLinkElement:null,hoverDelayTimeout:null};window.addEventListener("exdoc:loaded",Sl);function Sl(){M(yl).forEach(t=>{Ll(t)&&(t.addEventListener("mouseenter",_l),t.addEventListener("mouseleave",Ol))})}function Ll(t){return!(Tl(t.href)||!rr(t.href))}function Tl(t){let e=t.replace(wl,"");return window.location.href.split("#")[0]===e}function _l(t){if(window.innerWidth{ir(e.href).then(Pl).catch(()=>{})},kl)}function Pl(t){let e=qi({isPlain:t.kind===ie.plain,hint:t}),n=f(Fi);n||(f(Vi).insertAdjacentHTML("beforeend",vl),n=f(Fi)),n.innerHTML=e,Il(),f(kn).classList.add($i)}function Ol(){le.currentLinkElement&&(clearTimeout(le.hoverDelayTimeout),or(),le.currentLinkElement=null,f(kn)?.classList.remove($i))}function Il(){if(!le.currentLinkElement)return;let t=f(kn),e=le.currentLinkElement.getBoundingClientRect(),n=f(Vi).getBoundingClientRect(),r=t.getBoundingClientRect(),i=Al(e,n);if(e.left+r.width+Se code:first-child):not(:has(.copy-button))").forEach(t=>{if(!Sn){let r=document.createElement("div");r.innerHTML=Ui,Sn=r.firstChild}let e=Sn.cloneNode(!0);t.appendChild(e);let n;e.addEventListener("click",()=>{clearTimeout(n);let r=Array.from(t.querySelectorAll("code > *:not(.unselectable)")).map(i=>i.textContent).join("");navigator.clipboard.writeText(r),e.classList.add("clicked"),e.disabled=!0,n=setTimeout(()=>{e.classList.remove("clicked"),e.disabled=!1},3e3)})})}var V=Y(zi());var Gi=Y(ae());var Ki=Gi.template({1:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return" Search results for "+t.escapeExpression((s=(s=o(n,"value")||(e!=null?o(e,"value"):e))!=null?s:t.hooks.helperMissing,typeof s=="function"?s.call(e??(t.nullContext||{}),{name:"value",hash:{},data:i,loc:{start:{line:3,column:27},end:{line:3,column:36}}}):s))+` +`},3:function(t,e,n,r,i){return` Invalid search +`},5:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return(s=o(n,"each").call(e??(t.nullContext||{}),e!=null?o(e,"results"):e,{name:"each",hash:{},fn:t.program(6,i,0),inverse:t.noop,data:i,loc:{start:{line:10,column:2},end:{line:21,column:11}}}))!=null?s:""},6:function(t,e,n,r,i){var s,o=t.lambda,a=t.escapeExpression,l=t.lookupProperty||function(u,c){if(Object.prototype.hasOwnProperty.call(u,c))return u[c]};return`
+

+ + `+a(o(e!=null?l(e,"title"):e,e))+" ("+a(o(e!=null?l(e,"type"):e,e))+`) + +

+`+((s=l(n,"each").call(e??(t.nullContext||{}),e!=null?l(e,"excerpts"):e,{name:"each",hash:{},fn:t.program(7,i,0),inverse:t.noop,data:i,loc:{start:{line:17,column:8},end:{line:19,column:17}}}))!=null?s:"")+`
+`},7:function(t,e,n,r,i){var s;return'

'+((s=t.lambda(e,e))!=null?s:"")+`

+`},9:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return((s=(o(n,"isArray")||e&&o(e,"isArray")||t.hooks.helperMissing).call(e??(t.nullContext||{}),e!=null?o(e,"results"):e,{name:"isArray",hash:{},fn:t.program(10,i,0),inverse:t.program(12,i,0),data:i,loc:{start:{line:23,column:2},end:{line:29,column:14}}}))!=null?s:"")+` +

The search functionality is full-text based. Here are some tips:

+ +
    +
  • Multiple words (such as foo bar) are searched as OR
  • +
  • Use * anywhere (such as fo*) as wildcard
  • +
  • Use + before a word (such as +foo) to make its presence required
  • +
  • Use - before a word (such as -foo) to make its absence required
  • +
  • Use : to search on a particular field (such as field:word). The available fields are title, doc and type
  • +
  • Use WORD^NUMBER (such as foo^2) to boost the given word
  • +
  • Use WORD~NUMBER (such as foo~2) to do a search with edit distance on word
  • +
+ +

To quickly go to a module, type, or function, use the autocompletion feature in the sidebar search.

+`},10:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return"

Sorry, we couldn't find anything for "+t.escapeExpression((s=(s=o(n,"value")||(e!=null?o(e,"value"):e))!=null?s:t.hooks.helperMissing,typeof s=="function"?s.call(e??(t.nullContext||{}),{name:"value",hash:{},data:i,loc:{start:{line:24,column:48},end:{line:24,column:57}}}):s))+`.

+`},12:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return(s=o(n,"if").call(e??(t.nullContext||{}),e!=null?o(e,"value"):e,{name:"if",hash:{},fn:t.program(13,i,0),inverse:t.program(15,i,0),data:i,loc:{start:{line:25,column:2},end:{line:29,column:2}}}))!=null?s:""},13:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return"

Invalid search: "+t.escapeExpression((s=(s=o(n,"errorMessage")||(e!=null?o(e,"errorMessage"):e))!=null?s:t.hooks.helperMissing,typeof s=="function"?s.call(e??(t.nullContext||{}),{name:"errorMessage",hash:{},data:i,loc:{start:{line:26,column:23},end:{line:26,column:39}}}):s))+`.

+`},15:function(t,e,n,r,i){return`

Please type something into the search bar to perform a search.

+ `},compiler:[8,">= 4.3.0"],main:function(t,e,n,r,i){var s,o=e??(t.nullContext||{}),a=t.lookupProperty||function(l,u){if(Object.prototype.hasOwnProperty.call(l,u))return l[u]};return`

+`+((s=a(n,"if").call(o,e!=null?a(e,"value"):e,{name:"if",hash:{},fn:t.program(1,i,0),inverse:t.program(3,i,0),data:i,loc:{start:{line:2,column:2},end:{line:6,column:9}}}))!=null?s:"")+`

+ +`+((s=(a(n,"isNonEmptyArray")||e&&a(e,"isNonEmptyArray")||t.hooks.helperMissing).call(o,e!=null?a(e,"results"):e,{name:"isNonEmptyArray",hash:{},fn:t.program(5,i,0),inverse:t.program(9,i,0),data:i,loc:{start:{line:9,column:0},end:{line:44,column:20}}}))!=null?s:"")},useData:!0});var wt=80,Rl="#search";V.default.tokenizer.separator=/\s+/;V.default.QueryLexer.termSeparator=/\s+/;V.default.Pipeline.registerFunction(Xi,"docTokenSplitter");V.default.Pipeline.registerFunction(Zi,"docTrimmer");window.addEventListener("exdoc:loaded",Ml);function Ml(){let t=window.location.pathname;if(t.endsWith("/search.html")||t.endsWith("/search")){let e=er("q");Hl(e)}}async function Hl(t){if(he(t))Ln({value:t});else{Bi(t);let e=await Nl();try{let n=t.replaceAll(/(\B|\\):/g,"\\:"),r=Wl(e.search(n));Ln({value:t,results:r})}catch(n){Ln({value:t,errorMessage:n.message})}}}function Ln({value:t,results:e,errorMessage:n}){let r=f(Rl),i=Ki({value:t,results:e,errorMessage:n});r.innerHTML=i}async function Nl(){let t=await Dl();if(t)return t;let e=$l();return Bl(e),e}async function Dl(){try{let t=sessionStorage.getItem(Ji());if(t){let e=await ql(t);return V.default.Index.load(e)}else return null}catch(t){return console.error("Failed to load index: ",t),null}}async function Bl(t){try{let e=await Ql(t);sessionStorage.setItem(Ji(),e)}catch(e){console.error("Failed to save index: ",e)}}async function Ql(t){let e=new Blob([JSON.stringify(t)],{type:"application/json"}).stream().pipeThrough(new window.CompressionStream("gzip")),r=await(await new Response(e).blob()).arrayBuffer();return Fl(r)}async function ql(t){let e=new Blob([Vl(t)],{type:"application/json"}).stream().pipeThrough(new window.DecompressionStream("gzip")),n=await new Response(e).text();return JSON.parse(n)}function Fl(t){let e="",n=new Uint8Array(t),r=n.byteLength;for(let i=0;i{this.add(t)})})}function Ul(t){t.pipeline.before(V.default.stemmer,Xi)}function Xi(t){let e=[t],n=/\/\d+$/,r=/\:|\./,i=t.toString();if(i.replace(/^[.,;?!]+|[.,;]+$/g,""),i.startsWith("`")&&i.endsWith("`")&&(i=i.slice(1,-1)),n.test(i)){let o=t.toString().replace(n,"");e.push(t.clone().update(()=>o));let a=o.split(r);if(a.length>1){for(let u of a)e.push(t.clone().update(()=>u));let l=t.toString().split(r);e.push(t.clone().update(()=>l[l.length-1]))}i=a[a.length-1]}else i.startsWith("@")?(i=i.substring(1),e.push(t.clone().update(()=>i))):i.startsWith(":")&&(i=i.substring(1),e.push(t.clone().update(()=>i)));let s=i.split(/\_|\-/);if(s.length>1)for(let o of s)e.push(t.clone().update(()=>o));return e}function jl(t){t.pipeline.before(V.default.stemmer,Zi)}function Zi(t){return t.update(function(e){return e.replace(/^[^@:\w]+/,"").replace(/[^\?\!\w]+$/,"")})}function Wl(t){return t.filter(e=>Yi(e.ref)).map(e=>{let n=Yi(e.ref),r=e.matchData.metadata;return{...n,metadata:r,excerpts:zl(n,r)}})}function Yi(t){return searchData.items.find(e=>e.ref===t)||null}function zl(t,e){let{doc:n}=t,i=Object.keys(e).filter(s=>"doc"in e[s]).map(s=>e[s].doc.position.map(([o,a])=>Gl(n,o,a))).reduce((s,o)=>s.concat(o),[]);return i.length===0?[n.slice(0,wt*2)+(wt*20?"...":"",t.slice(r,e),""+Re(t.slice(e,e+n))+"",t.slice(e+n,i),i{t.key==="Escape"&&ue()}),N.querySelector(".modal-close").addEventListener("click",ue),N.addEventListener("click",t=>{t.target===N&&ue()}))}function ts(t){if(!_n)if(N.contains(t.target))Tn=t.target;else{_n=!0;let e=N.querySelectorAll(Kl);Tn===e[0]?e[e.length-1].focus():e[0].focus(),_n=!1,Tn=document.activeElement}}function bt({title:t,body:e}){Yl(),Pn=document.activeElement,document.addEventListener("focus",ts,!0),N.querySelector(".modal-title").innerHTML=t,N.querySelector(".modal-body").innerHTML=e,N.classList.add("shown"),N.focus()}function ue(){N?.classList.remove("shown"),document.removeEventListener("focus",ts,!0),Pn?.focus(),Pn=null}function ns(){return Boolean(N?.classList.contains("shown"))}var rs='
';var Jl="https://hexdocs.pm/%%",Xl="https://www.erlang.org/doc/apps/%%",Zl="https://hex.pm/api/packages?search=name:%%*",eu=".display-quick-switch",ss="#quick-switch-input",os="#quick-switch-results",tu=300,nu=9,as=["erts","asn1","common_test","compiler","crypto","debugger","dialyzer","diameter","edoc","eldap","erl_interface","et","eunit","ftp","inets","jinterface","kernel","megaco","mnesia","observer","odbc","os_mon","parsetools","public_key","reltool","runtime_tools","sasl","snmp","ssh","ssl","stdlib","syntax_tools","tftp","tools","wx","xmerl"],ru=["elixir","eex","ex_unit","hex","iex","logger","mix"].concat(as).map(t=>({name:t})),ls=2,B={autocompleteResults:[],selectedIdx:null};A||window.addEventListener("exdoc:loaded",iu);function iu(){M(eu).forEach(t=>{t.addEventListener("click",In)})}function su(t){if(t.key==="Enter"){let e=t.target.value;au(e),t.preventDefault()}else t.key==="ArrowUp"?(is(-1),t.preventDefault()):t.key==="ArrowDown"&&(is(1),t.preventDefault())}function ou(t){let e=t.target.value;if(e.lengthn.json()).then(n=>{Array.isArray(n)&&(B.autocompleteResults=du(t,n),B.selectedIdx=null,f(ss).value.length>=ls&&cu(B.autocompleteResults))})}function cu(t){f(os).replaceChildren(...t.map(({name:e},n)=>{let r=E("div",{class:"quick-switch-result","data-index":n},[e]);return r.addEventListener("click",()=>On(e)),r}))}function du(t,e){return ru.concat(e).filter(n=>n.name.toLowerCase().includes(t.toLowerCase())).filter(n=>n.releases===void 0||n.releases[0].has_docs===!0).slice(0,nu)}function is(t){B.selectedIdx=hu(t);let e=f(".quick-switch-result.selected"),n=f(`.quick-switch-result[data-index="${B.selectedIdx}"]`);e&&e.classList.remove("selected"),n&&n.classList.add("selected")}function hu(t){let e=B.autocompleteResults.length;if(B.selectedIdx===null){if(t>=0)return 0;if(t<0)return e-1}return(B.selectedIdx+t+e)%e}var fu="#settings-modal-content",Rn=[{key:"c",description:"Toggle sidebar",action:Ue},{key:"n",description:"Cycle themes",action:pr},{key:"s",description:"Focus search bar",displayAs:"/ or s",action:An},{key:"/",action:An},{key:"k",hasModifier:!0,action:An},{key:"v",description:"Open/focus version select",action:gu},{key:"g",description:"Go to package docs",displayAs:"g",action:In},{key:"?",displayAs:"?",description:"Bring up this modal",action:vu}],Cn={shortcutBeingPressed:null};A||(document.addEventListener("keydown",pu),document.addEventListener("keyup",mu));function pu(t){if(Cn.shortcutBeingPressed||t.target.matches("input, select, textarea"))return;let e=Rn.find(n=>n.hasModifier?De()&&t.metaKey||t.ctrlKey?n.key===t.key:!1:t.ctrlKey||t.metaKey||t.altKey?!1:n.key===t.key);e&&(Cn.shortcutBeingPressed=e,t.preventDefault(),e.action(t))}function mu(t){Cn.shortcutBeingPressed=null}function An(t){ue(),xn()}function gu(){ue(),Or()?pn():Ar().then(pn)}function vu(){yu()?ue():Mn()}function yu(){return ns()&&f(fu)}var us=Y(ae());var cs=us.template({1:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return(s=o(n,"if").call(e??(t.nullContext||{}),e!=null?o(e,"description"):e,{name:"if",hash:{},fn:t.program(2,i,0),inverse:t.noop,data:i,loc:{start:{line:40,column:6},end:{line:53,column:13}}}))!=null?s:""},2:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return`
+
+ `+t.escapeExpression(t.lambda(e!=null?o(e,"description"):e,e))+` +
+
+`+((s=o(n,"if").call(e??(t.nullContext||{}),e!=null?o(e,"displayAs"):e,{name:"if",hash:{},fn:t.program(3,i,0),inverse:t.program(5,i,0),data:i,loc:{start:{line:46,column:12},end:{line:50,column:19}}}))!=null?s:"")+`
+
+`},3:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return" "+((s=t.lambda(e!=null?o(e,"displayAs"):e,e))!=null?s:"")+` +`},5:function(t,e,n,r,i){var s=t.lookupProperty||function(o,a){if(Object.prototype.hasOwnProperty.call(o,a))return o[a]};return" "+t.escapeExpression(t.lambda(e!=null?s(e,"key"):e,e))+` +`},compiler:[8,">= 4.3.0"],main:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return`
+
+ + + + +
+ +
+`},useData:!0});var wu=".display-settings",bu="#settings-modal-content",Hn="#modal-settings-tab",Nn="#modal-keyboard-shortcuts-tab",hs="#settings-content",fs="#keyboard-shortcuts-content",Eu=[{title:"Settings",id:"modal-settings-tab"},{title:"Keyboard shortcuts",id:"modal-keyboard-shortcuts-tab"}];window.addEventListener("exdoc:loaded",xu);function xu(){M(wu).forEach(t=>{t.addEventListener("click",Mn)})}function ds(){f(Nn).classList.remove("active"),f(Hn).classList.add("active"),f(hs).classList.remove("hidden"),f(fs).classList.add("hidden")}function ku(){f(Nn).classList.add("active"),f(Hn).classList.remove("active"),f(fs).classList.remove("hidden"),f(hs).classList.add("hidden")}function Mn(){bt({title:Eu.map(({id:s,title:o})=>``).join(""),body:cs({shortcuts:Rn})});let t=f(bu),e=t.querySelector('[name="theme"]'),n=t.querySelector('[name="tooltips"]'),r=t.querySelector('[name="direct_livebook_url"]'),i=t.querySelector('[name="livebook_url"]');H.getAndSubscribe(s=>{e.value=s.theme||"system",n.checked=s.tooltips,s.livebookUrl===null?(r.checked=!1,i.classList.add("hidden"),i.tabIndex=-1):(r.checked=!0,i.classList.remove("hidden"),i.tabIndex=0,i.value=s.livebookUrl)}),e.addEventListener("change",s=>{H.update({theme:s.target.value})}),n.addEventListener("change",s=>{H.update({tooltips:s.target.checked})}),r.addEventListener("change",s=>{let o=s.target.checked?i.value:null;H.update({livebookUrl:o})}),i.addEventListener("input",s=>{H.update({livebookUrl:s.target.value})}),f(Hn).addEventListener("click",s=>{ds()}),f(Nn).addEventListener("click",s=>{ku()}),ds()}var Dn=new WeakMap;function Bn(t,e,n,r){if(!t&&!Dn.has(e))return!1;let i=Dn.get(e)??new WeakMap;Dn.set(e,i);let s=i.get(n)??new Set;i.set(n,s);let o=s.has(r);return t?s.add(r):s.delete(r),o&&t}function Su(t,e){let n=t.target;if(n instanceof Text&&(n=n.parentElement),n instanceof Element&&t.currentTarget instanceof Element){let r=n.closest(e);if(r&&t.currentTarget.contains(r))return r}}function Lu(t,e,n,r={}){let{signal:i,base:s=document}=r;if(i?.aborted)return;let{once:o,...a}=r,l=s instanceof Document?s.documentElement:s,u=Boolean(typeof r=="object"?r.capture:r),c=p=>{let g=Su(p,String(t));if(g){let m=Object.assign(p,{delegateTarget:g});n.call(l,m),o&&(l.removeEventListener(e,c,a),Bn(!1,l,n,d))}},d=JSON.stringify({selector:t,type:e,capture:u});Bn(!0,l,n,d)||l.addEventListener(e,c,a),i?.addEventListener("abort",()=>{Bn(!1,l,n,d)})}var Et=Lu;function O(){return O=Object.assign?Object.assign.bind():function(t){for(var e=1;eString(t).toLowerCase().replace(/[\s/_.]+/g,"-").replace(/[^\w-]+/g,"").replace(/--+/g,"-").replace(/^-+|-+$/g,"")||e||"",Te=({hash:t}={})=>window.location.pathname+window.location.search+(t?window.location.hash:""),Tu=(t,e={})=>{let n=O({url:t=t||Te({hash:!0}),random:Math.random(),source:"swup"},e);window.history.pushState(n,"",t)},Le=(t=null,e={})=>{t=t||Te({hash:!0});let n=O({},window.history.state||{},{url:t,random:Math.random(),source:"swup"},e);window.history.replaceState(n,"",t)},_u=(t,e,n,r)=>{let i=new AbortController;return r=O({},r,{signal:i.signal}),Et(t,e,n,r),{destroy:()=>i.abort()}},I=class extends URL{constructor(e,n=document.baseURI){super(e.toString(),n),Object.setPrototypeOf(this,I.prototype)}get url(){return this.pathname+this.search}static fromElement(e){let n=e.getAttribute("href")||e.getAttribute("xlink:href")||"";return new I(n)}static fromUrl(e){return new I(e)}};var me=class extends Error{constructor(e,n){super(e),this.url=void 0,this.status=void 0,this.aborted=void 0,this.timedOut=void 0,this.name="FetchError",this.url=n.url,this.status=n.status,this.aborted=n.aborted||!1,this.timedOut=n.timedOut||!1}};async function Pu(t,e={}){var n;t=I.fromUrl(t).url;let{visit:r=this.visit}=e,i=O({},this.options.requestHeaders,e.headers),s=(n=e.timeout)!=null?n:this.options.timeout,o=new AbortController,{signal:a}=o;e=O({},e,{headers:i,signal:a});let l,u=!1,c=null;s&&s>0&&(c=setTimeout(()=>{u=!0,o.abort("timeout")},s));try{l=await this.hooks.call("fetch:request",r,{url:t,options:e},(v,{url:w,options:x})=>fetch(w,x)),c&&clearTimeout(c)}catch(v){throw u?(this.hooks.call("fetch:timeout",r,{url:t}),new me(`Request timed out: ${t}`,{url:t,timedOut:u})):v?.name==="AbortError"||a.aborted?new me(`Request aborted: ${t}`,{url:t,aborted:!0}):v}let{status:d,url:h}=l,p=await l.text();if(d===500)throw this.hooks.call("fetch:error",r,{status:d,response:l,url:h}),new me(`Server error: ${h}`,{status:d,url:h});if(!p)throw new me(`Empty response: ${h}`,{status:d,url:h});let{url:g}=I.fromUrl(h),m={url:g,html:p};return!r.cache.write||e.method&&e.method!=="GET"||t!==g||this.cache.set(m.url,m),m}var qn=class{constructor(e){this.swup=void 0,this.pages=new Map,this.swup=e}get size(){return this.pages.size}get all(){let e=new Map;return this.pages.forEach((n,r)=>{e.set(r,O({},n))}),e}has(e){return this.pages.has(this.resolve(e))}get(e){let n=this.pages.get(this.resolve(e));return n&&O({},n)}set(e,n){n=O({},n,{url:e=this.resolve(e)}),this.pages.set(e,n),this.swup.hooks.callSync("cache:set",void 0,{page:n})}update(e,n){e=this.resolve(e);let r=O({},this.get(e),n,{url:e});this.pages.set(e,r)}delete(e){this.pages.delete(this.resolve(e))}clear(){this.pages.clear(),this.swup.hooks.callSync("cache:clear",void 0,void 0)}prune(e){this.pages.forEach((n,r)=>{e(r,n)&&this.delete(r)})}resolve(e){let{url:n}=I.fromUrl(e);return this.swup.resolveUrl(n)}},Fn=(t,e=document)=>e.querySelector(t),Un=(t,e=document)=>Array.from(e.querySelectorAll(t)),ys=()=>new Promise(t=>{requestAnimationFrame(()=>{requestAnimationFrame(()=>{t()})})});function ws(t){return!!t&&(typeof t=="object"||typeof t=="function")&&typeof t.then=="function"}function Ou(t,e=[]){return new Promise((n,r)=>{let i=t(...e);ws(i)?i.then(n,r):n(i)})}function ps(t,e){let n=t?.closest(`[${e}]`);return n!=null&&n.hasAttribute(e)?n?.getAttribute(e)||!0:void 0}var Vn=class{constructor(e){this.swup=void 0,this.swupClasses=["to-","is-changing","is-rendering","is-popstate","is-animating","is-leaving"],this.swup=e}get selectors(){let{scope:e}=this.swup.visit.animation;return e==="containers"?this.swup.visit.containers:e==="html"?["html"]:Array.isArray(e)?e:[]}get selector(){return this.selectors.join(",")}get targets(){return this.selector.trim()?Un(this.selector):[]}add(...e){this.targets.forEach(n=>n.classList.add(...e))}remove(...e){this.targets.forEach(n=>n.classList.remove(...e))}clear(){this.targets.forEach(e=>{let n=e.className.split(" ").filter(r=>this.isSwupClass(r));e.classList.remove(...n)})}isSwupClass(e){return this.swupClasses.some(n=>e.startsWith(n))}},St=class{constructor(e,n){this.id=void 0,this.state=void 0,this.from=void 0,this.to=void 0,this.containers=void 0,this.animation=void 0,this.trigger=void 0,this.cache=void 0,this.history=void 0,this.scroll=void 0,this.meta=void 0;let{to:r,from:i,hash:s,el:o,event:a}=n;this.id=Math.random(),this.state=1,this.from={url:i??e.location.url,hash:e.location.hash},this.to={url:r,hash:s},this.containers=e.options.containers,this.animation={animate:!0,wait:!1,name:void 0,native:e.options.native,scope:e.options.animationScope,selector:e.options.animationSelector},this.trigger={el:o,event:a},this.cache={read:e.options.cache,write:e.options.cache},this.history={action:"push",popstate:!1,direction:void 0},this.scroll={reset:!0,target:void 0},this.meta={}}advance(e){this.state=7}};function Iu(t){return new St(this,t)}var $n=class{constructor(e){this.swup=void 0,this.registry=new Map,this.hooks=["animation:out:start","animation:out:await","animation:out:end","animation:in:start","animation:in:await","animation:in:end","animation:skip","cache:clear","cache:set","content:replace","content:scroll","enable","disable","fetch:request","fetch:error","fetch:timeout","history:popstate","link:click","link:self","link:anchor","link:newtab","page:load","page:view","scroll:top","scroll:anchor","visit:start","visit:transition","visit:abort","visit:end"],this.swup=e,this.init()}init(){this.hooks.forEach(e=>this.create(e))}create(e){this.registry.has(e)||this.registry.set(e,new Map)}exists(e){return this.registry.has(e)}get(e){let n=this.registry.get(e);if(n)return n;console.error(`Unknown hook '${e}'`)}clear(){this.registry.forEach(e=>e.clear())}on(e,n,r={}){let i=this.get(e);if(!i)return console.warn(`Hook '${e}' not found.`),()=>{};let s=O({},r,{id:i.size+1,hook:e,handler:n});return i.set(n,s),()=>this.off(e,n)}before(e,n,r={}){return this.on(e,n,O({},r,{before:!0}))}replace(e,n,r={}){return this.on(e,n,O({},r,{replace:!0}))}once(e,n,r={}){return this.on(e,n,O({},r,{once:!0}))}off(e,n){let r=this.get(e);r&&n?r.delete(n)||console.warn(`Handler for hook '${e}' not found.`):r&&r.clear()}async call(e,n,r,i){let[s,o,a]=this.parseCallArgs(e,n,r,i),{before:l,handler:u,after:c}=this.getHandlers(e,a);await this.run(l,s,o);let[d]=await this.run(u,s,o,!0);return await this.run(c,s,o),this.dispatchDomEvent(e,s,o),d}callSync(e,n,r,i){let[s,o,a]=this.parseCallArgs(e,n,r,i),{before:l,handler:u,after:c}=this.getHandlers(e,a);this.runSync(l,s,o);let[d]=this.runSync(u,s,o,!0);return this.runSync(c,s,o),this.dispatchDomEvent(e,s,o),d}parseCallArgs(e,n,r,i){return n instanceof St||typeof n!="object"&&typeof r!="function"?[n,r,i]:[void 0,n,r]}async run(e,n=this.swup.visit,r,i=!1){let s=[];for(let{hook:o,handler:a,defaultHandler:l,once:u}of e)if(n==null||!n.done){u&&this.off(o,a);try{let c=await Ou(a,[n,r,l]);s.push(c)}catch(c){if(i)throw c;console.error(`Error in hook '${o}':`,c)}}return s}runSync(e,n=this.swup.visit,r,i=!1){let s=[];for(let{hook:o,handler:a,defaultHandler:l,once:u}of e)if(n==null||!n.done){u&&this.off(o,a);try{let c=a(n,r,l);s.push(c),ws(c)&&console.warn(`Swup will not await Promises in handler for synchronous hook '${o}'.`)}catch(c){if(i)throw c;console.error(`Error in hook '${o}':`,c)}}return s}getHandlers(e,n){let r=this.get(e);if(!r)return{found:!1,before:[],handler:[],after:[],replaced:!1};let i=Array.from(r.values()),s=this.sortRegistrations,o=i.filter(({before:d,replace:h})=>d&&!h).sort(s),a=i.filter(({replace:d})=>d).filter(d=>!0).sort(s),l=i.filter(({before:d,replace:h})=>!d&&!h).sort(s),u=a.length>0,c=[];if(n&&(c=[{id:0,hook:e,handler:n}],u)){let d=a.length-1,{handler:h,once:p}=a[d],g=m=>{let v=a[m-1];return v?(w,x)=>v.handler(w,x,g(m-1)):n};c=[{id:0,hook:e,once:p,handler:h,defaultHandler:g(d)}]}return{found:!0,before:o,handler:c,after:l,replaced:u}}sortRegistrations(e,n){var r,i;return((r=e.priority)!=null?r:0)-((i=n.priority)!=null?i:0)||e.id-n.id||0}dispatchDomEvent(e,n,r){if(n!=null&&n.done)return;let i={hook:e,args:r,visit:n||this.swup.visit};document.dispatchEvent(new CustomEvent("swup:any",{detail:i,bubbles:!0})),document.dispatchEvent(new CustomEvent(`swup:${e}`,{detail:i,bubbles:!0}))}parseName(e){let[n,...r]=e.split(".");return[n,r.reduce((i,s)=>O({},i,{[s]:!0}),{})]}},Au=t=>{if(t&&t.charAt(0)==="#"&&(t=t.substring(1)),!t)return null;let e=decodeURIComponent(t),n=document.getElementById(t)||document.getElementById(e)||Fn(`a[name='${CSS.escape(t)}']`)||Fn(`a[name='${CSS.escape(e)}']`);return n||t!=="top"||(n=document.body),n},xt="transition",Qn="animation";async function Cu({selector:t,elements:e}){if(t===!1&&!e)return;let n=[];if(e)n=Array.from(e);else if(t&&(n=Un(t,document.body),!n.length))return void console.warn(`[swup] No elements found matching animationSelector \`${t}\``);let r=n.map(i=>function(s){let{type:o,timeout:a,propCount:l}=function(u){let c=window.getComputedStyle(u),d=kt(c,`${xt}Delay`),h=kt(c,`${xt}Duration`),p=ms(d,h),g=kt(c,`${Qn}Delay`),m=kt(c,`${Qn}Duration`),v=ms(g,m),w=Math.max(p,v),x=w>0?p>v?xt:Qn:null;return{type:x,timeout:w,propCount:x?x===xt?h.length:m.length:0}}(s);return!(!o||!a)&&new Promise(u=>{let c=`${o}end`,d=performance.now(),h=0,p=()=>{s.removeEventListener(c,g),u()},g=m=>{m.target===s&&((performance.now()-d)/1e3=l&&p())};setTimeout(()=>{h0?await Promise.all(r):t&&console.warn(`[swup] No CSS animation duration defined on elements matching \`${t}\``)}function kt(t,e){return(t[e]||"").split(", ")}function ms(t,e){for(;t.lengthgs(n)+gs(t[r])))}function gs(t){return 1e3*parseFloat(t)}function Ru(t,e={},n={}){if(typeof t!="string")throw new Error("swup.navigate() requires a URL parameter");if(this.shouldIgnoreVisit(t,{el:n.el,event:n.event}))return void window.location.assign(t);let{url:r,hash:i}=I.fromUrl(t),s=this.createVisit(O({},n,{to:r,hash:i}));this.performNavigation(s,e)}async function Mu(t,e={}){if(this.navigating){if(this.visit.state>=6)return t.state=2,void(this.onVisitEnd=()=>this.performNavigation(t,e));await this.hooks.call("visit:abort",this.visit,void 0),delete this.visit.to.document,this.visit.state=8}this.navigating=!0,this.visit=t;let{el:n}=t.trigger;e.referrer=e.referrer||this.location.url,e.animate===!1&&(t.animation.animate=!1),t.animation.animate||this.classes.clear();let r=e.history||ps(n,"data-swup-history");typeof r=="string"&&["push","replace"].includes(r)&&(t.history.action=r);let i=e.animation||ps(n,"data-swup-animation");var s,o;typeof i=="string"&&(t.animation.name=i),t.meta=e.meta||{},typeof e.cache=="object"?(t.cache.read=(s=e.cache.read)!=null?s:t.cache.read,t.cache.write=(o=e.cache.write)!=null?o:t.cache.write):e.cache!==void 0&&(t.cache={read:!!e.cache,write:!!e.cache}),delete e.cache;try{await this.hooks.call("visit:start",t,void 0),t.state=3;let a=this.hooks.call("page:load",t,{options:e},async(u,c)=>{let d;return u.cache.read&&(d=this.cache.get(u.to.url)),c.page=d||await this.fetchPage(u.to.url,c.options),c.cache=!!d,c.page});a.then(({html:u})=>{t.advance(5),t.to.html=u,t.to.document=new DOMParser().parseFromString(u,"text/html")});let l=t.to.url+t.to.hash;if(t.history.popstate||(t.history.action==="replace"||t.to.url===this.location.url?Le(l):(this.currentHistoryIndex++,Tu(l,{index:this.currentHistoryIndex}))),this.location=I.fromUrl(l),t.history.popstate&&this.classes.add("is-popstate"),t.animation.name&&this.classes.add(`to-${vs(t.animation.name)}`),t.animation.wait&&await a,t.done||(await this.hooks.call("visit:transition",t,void 0,async()=>{if(!t.animation.animate)return await this.hooks.call("animation:skip",void 0),void await this.renderPage(t,await a);t.advance(4),await this.animatePageOut(t),t.animation.native&&document.startViewTransition?await document.startViewTransition(async()=>await this.renderPage(t,await a)).finished:await this.renderPage(t,await a),await this.animatePageIn(t)}),t.done))return;await this.hooks.call("visit:end",t,void 0,()=>this.classes.clear()),t.state=7,this.navigating=!1,this.onVisitEnd&&(this.onVisitEnd(),this.onVisitEnd=void 0)}catch(a){if(!a||a!=null&&a.aborted)return void(t.state=8);t.state=9,console.error(a),this.options.skipPopStateHandling=()=>(window.location.assign(t.to.url+t.to.hash),!0),window.history.back()}finally{delete t.to.document}}var Hu=async function(t){await this.hooks.call("animation:out:start",t,void 0,()=>{this.classes.add("is-changing","is-animating","is-leaving")}),await this.hooks.call("animation:out:await",t,{skip:!1},(e,{skip:n})=>{if(!n)return this.awaitAnimations({selector:e.animation.selector})}),await this.hooks.call("animation:out:end",t,void 0)},Nu=function(t){var e;let n=t.to.document;if(!n)return!1;let r=((e=n.querySelector("title"))==null?void 0:e.innerText)||"";document.title=r;let i=Un('[data-swup-persist]:not([data-swup-persist=""])'),s=t.containers.map(o=>{let a=document.querySelector(o),l=n.querySelector(o);return a&&l?(a.replaceWith(l.cloneNode(!0)),!0):(a||console.warn(`[swup] Container missing in current document: ${o}`),l||console.warn(`[swup] Container missing in incoming document: ${o}`),!1)}).filter(Boolean);return i.forEach(o=>{let a=o.getAttribute("data-swup-persist"),l=Fn(`[data-swup-persist="${a}"]`);l&&l!==o&&l.replaceWith(o)}),s.length===t.containers.length},Du=function(t){let e={behavior:"auto"},{target:n,reset:r}=t.scroll,i=n??t.to.hash,s=!1;return i&&(s=this.hooks.callSync("scroll:anchor",t,{hash:i,options:e},(o,{hash:a,options:l})=>{let u=this.getAnchorElement(a);return u&&u.scrollIntoView(l),!!u})),r&&!s&&(s=this.hooks.callSync("scroll:top",t,{options:e},(o,{options:a})=>(window.scrollTo(O({top:0,left:0},a)),!0))),s},Bu=async function(t){if(t.done)return;let e=this.hooks.call("animation:in:await",t,{skip:!1},(n,{skip:r})=>{if(!r)return this.awaitAnimations({selector:n.animation.selector})});await ys(),await this.hooks.call("animation:in:start",t,void 0,()=>{this.classes.remove("is-animating")}),await e,await this.hooks.call("animation:in:end",t,void 0)},Qu=async function(t,e){if(t.done)return;t.advance(6);let{url:n}=e;this.isSameResolvedUrl(Te(),n)||(Le(n),this.location=I.fromUrl(n),t.to.url=this.location.url,t.to.hash=this.location.hash),await this.hooks.call("content:replace",t,{page:e},(r,{})=>{if(this.classes.remove("is-leaving"),r.animation.animate&&this.classes.add("is-rendering"),!this.replaceContent(r))throw new Error("[swup] Container mismatch, aborting");r.animation.animate&&(this.classes.add("is-changing","is-animating","is-rendering"),r.animation.name&&this.classes.add(`to-${vs(r.animation.name)}`))}),await this.hooks.call("content:scroll",t,void 0,()=>this.scrollToContent(t)),await this.hooks.call("page:view",t,{url:this.location.url,title:document.title})},qu=function(t){var e;if(e=t,Boolean(e?.isSwupPlugin)){if(t.swup=this,!t._checkRequirements||t._checkRequirements())return t._beforeMount&&t._beforeMount(),t.mount(),this.plugins.push(t),this.plugins}else console.error("Not a swup plugin instance",t)};function Fu(t){let e=this.findPlugin(t);if(e)return e.unmount(),e._afterUnmount&&e._afterUnmount(),this.plugins=this.plugins.filter(n=>n!==e),this.plugins;console.error("No such plugin",e)}function Vu(t){return this.plugins.find(e=>e===t||e.name===t||e.name===`Swup${String(t)}`)}function $u(t){if(typeof this.options.resolveUrl!="function")return console.warn("[swup] options.resolveUrl expects a callback function."),t;let e=this.options.resolveUrl(t);return e&&typeof e=="string"?e.startsWith("//")||e.startsWith("http")?(console.warn("[swup] options.resolveUrl needs to return a relative url"),t):e:(console.warn("[swup] options.resolveUrl needs to return a url"),t)}function Uu(t,e){return this.resolveUrl(t)===this.resolveUrl(e)}var ju={animateHistoryBrowsing:!1,animationSelector:'[class*="transition-"]',animationScope:"html",cache:!0,containers:["#swup"],hooks:{},ignoreVisit:(t,{el:e}={})=>!(e==null||!e.closest("[data-no-swup]")),linkSelector:"a[href]",linkToSelf:"scroll",native:!1,plugins:[],resolveUrl:t=>t,requestHeaders:{"X-Requested-With":"swup",Accept:"text/html, application/xhtml+xml"},skipPopStateHandling:t=>{var e;return((e=t.state)==null?void 0:e.source)!=="swup"},timeout:0},Lt=class{get currentPageUrl(){return this.location.url}constructor(e={}){var n,r;this.version="4.8.1",this.options=void 0,this.defaults=ju,this.plugins=[],this.visit=void 0,this.cache=void 0,this.hooks=void 0,this.classes=void 0,this.location=I.fromUrl(window.location.href),this.currentHistoryIndex=void 0,this.clickDelegate=void 0,this.navigating=!1,this.onVisitEnd=void 0,this.use=qu,this.unuse=Fu,this.findPlugin=Vu,this.log=()=>{},this.navigate=Ru,this.performNavigation=Mu,this.createVisit=Iu,this.delegateEvent=_u,this.fetchPage=Pu,this.awaitAnimations=Cu,this.renderPage=Qu,this.replaceContent=Nu,this.animatePageIn=Bu,this.animatePageOut=Hu,this.scrollToContent=Du,this.getAnchorElement=Au,this.getCurrentUrl=Te,this.resolveUrl=$u,this.isSameResolvedUrl=Uu,this.options=O({},this.defaults,e),this.handleLinkClick=this.handleLinkClick.bind(this),this.handlePopState=this.handlePopState.bind(this),this.cache=new qn(this),this.classes=new Vn(this),this.hooks=new $n(this),this.visit=this.createVisit({to:""}),this.currentHistoryIndex=(n=(r=window.history.state)==null?void 0:r.index)!=null?n:1,this.enable()}async enable(){var e;let{linkSelector:n}=this.options;this.clickDelegate=this.delegateEvent(n,"click",this.handleLinkClick),window.addEventListener("popstate",this.handlePopState),this.options.animateHistoryBrowsing&&(window.history.scrollRestoration="manual"),this.options.native=this.options.native&&!!document.startViewTransition,this.options.plugins.forEach(r=>this.use(r));for(let[r,i]of Object.entries(this.options.hooks)){let[s,o]=this.hooks.parseName(r);this.hooks.on(s,i,o)}((e=window.history.state)==null?void 0:e.source)!=="swup"&&Le(null,{index:this.currentHistoryIndex}),await ys(),await this.hooks.call("enable",void 0,void 0,()=>{let r=document.documentElement;r.classList.add("swup-enabled"),r.classList.toggle("swup-native",this.options.native)})}async destroy(){this.clickDelegate.destroy(),window.removeEventListener("popstate",this.handlePopState),this.cache.clear(),this.options.plugins.forEach(e=>this.unuse(e)),await this.hooks.call("disable",void 0,void 0,()=>{let e=document.documentElement;e.classList.remove("swup-enabled"),e.classList.remove("swup-native")}),this.hooks.clear()}shouldIgnoreVisit(e,{el:n,event:r}={}){let{origin:i,url:s,hash:o}=I.fromUrl(e);return i!==window.location.origin||!(!n||!this.triggerWillOpenNewWindow(n))||!!this.options.ignoreVisit(s+o,{el:n,event:r})}handleLinkClick(e){let n=e.delegateTarget,{href:r,url:i,hash:s}=I.fromElement(n);if(this.shouldIgnoreVisit(r,{el:n,event:e}))return;if(this.navigating&&i===this.visit.to.url)return void e.preventDefault();let o=this.createVisit({to:i,hash:s,el:n,event:e});e.metaKey||e.ctrlKey||e.shiftKey||e.altKey?this.hooks.callSync("link:newtab",o,{href:r}):e.button===0&&this.hooks.callSync("link:click",o,{el:n,event:e},()=>{var a;let l=(a=o.from.url)!=null?a:"";e.preventDefault(),i&&i!==l?this.isSameResolvedUrl(i,l)||this.performNavigation(o):s?this.hooks.callSync("link:anchor",o,{hash:s},()=>{Le(i+s),this.scrollToContent(o)}):this.hooks.callSync("link:self",o,void 0,()=>{this.options.linkToSelf==="navigate"?this.performNavigation(o):(Le(i),this.scrollToContent(o))})})}handlePopState(e){var n,r,i,s;let o=(n=(r=e.state)==null?void 0:r.url)!=null?n:window.location.href;if(this.options.skipPopStateHandling(e)||this.isSameResolvedUrl(Te(),this.location.url))return;let{url:a,hash:l}=I.fromUrl(o),u=this.createVisit({to:a,hash:l,event:e});u.history.popstate=!0;let c=(i=(s=e.state)==null?void 0:s.index)!=null?i:0;c&&c!==this.currentHistoryIndex&&(u.history.direction=c-this.currentHistoryIndex>0?"forwards":"backwards",this.currentHistoryIndex=c),u.animation.animate=!1,u.scroll.reset=!1,u.scroll.target=!1,this.options.animateHistoryBrowsing&&(u.animation.animate=!0,u.scroll.reset=!0),this.hooks.callSync("history:popstate",u,{event:e},()=>{this.performNavigation(u)})}triggerWillOpenNewWindow(e){return!!e.matches('[download], [target="_blank"]')}};function _e(){return _e=Object.assign?Object.assign.bind():function(t){for(var e=1;eString(t).split(".").map(e=>String(parseInt(e||"0",10))).concat(["0","0"]).slice(0,3).join("."),ge=class{constructor(){this.isSwupPlugin=!0,this.swup=void 0,this.version=void 0,this.requires={},this.handlersToUnregister=[]}mount(){}unmount(){this.handlersToUnregister.forEach(e=>e()),this.handlersToUnregister=[]}_beforeMount(){if(!this.name)throw new Error("You must define a name of plugin when creating a class.")}_afterUnmount(){}_checkRequirements(){return typeof this.requires!="object"||Object.entries(this.requires).forEach(([e,n])=>{if(!function(r,i,s){let o=function(a,l){var u;if(a==="swup")return(u=l.version)!=null?u:"";{var c;let d=l.findPlugin(a);return(c=d?.version)!=null?c:""}}(r,s);return!!o&&((a,l)=>l.every(u=>{let[,c,d]=u.match(/^([\D]+)?(.*)$/)||[];var h,p;return((g,m)=>{let v={"":w=>w===0,">":w=>w>0,">=":w=>w>=0,"<":w=>w<0,"<=":w=>w<=0};return(v[m]||v[""])(g)})((p=d,h=bs(h=a),p=bs(p),h.localeCompare(p,void 0,{numeric:!0})),c||">=")}))(o,i)}(e,n=Array.isArray(n)?n:[n],this.swup)){let r=`${e} ${n.join(", ")}`;throw new Error(`Plugin version mismatch: ${this.name} requires ${r}`)}}),!0}on(e,n,r={}){var i;n=!(i=n).name.startsWith("bound ")||i.hasOwnProperty("prototype")?n.bind(this):n;let s=this.swup.hooks.on(e,n,r);return this.handlersToUnregister.push(s),s}once(e,n,r={}){return this.on(e,n,_e({},r,{once:!0}))}before(e,n,r={}){return this.on(e,n,_e({},r,{before:!0}))}replace(e,n,r={}){return this.on(e,n,_e({},r,{replace:!0}))}off(e,n){return this.swup.hooks.off(e,n)}};(function(){if(!(typeof window>"u"||typeof document>"u"||typeof HTMLElement>"u")){var t=!1;try{var e=document.createElement("div");e.addEventListener("focus",function(s){s.preventDefault(),s.stopPropagation()},!0),e.focus(Object.defineProperty({},"preventScroll",{get:function(){if(navigator&&typeof navigator.userAgent<"u"&&navigator.userAgent&&navigator.userAgent.match(/Edge\/1[7-8]/))return t=!1;t=!0}}))}catch{}if(HTMLElement.prototype.nativeFocus===void 0&&!t){HTMLElement.prototype.nativeFocus=HTMLElement.prototype.focus;var n=function(s){for(var o=s.parentNode,a=[],l=document.scrollingElement||document.documentElement;o&&o!==l;)(o.offsetHeightn.replace(`{${r}}`,e[r]||""),t||"")}var Wn=class{constructor(){var e;this.id="swup-announcer",this.style="position:absolute;top:0;left:0;clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden;white-space:nowrap;word-wrap:normal;width:1px;height:1px;",this.region=void 0,this.region=(e=this.getRegion())!=null?e:this.createRegion()}getRegion(){return document.getElementById(this.id)}createRegion(){let e=function(n){let r=document.createElement("template");return r.innerHTML=n,r.content.children[0]}(`

`);return document.body.appendChild(e),e}announce(e,n=0){return new Promise(r=>{setTimeout(()=>{this.region.textContent===e&&(e=`${e}.`),this.region.textContent="",this.region.textContent=e,r()},n)})}};function xs(t){let e;if(e=typeof t=="string"?document.querySelector(t):t,!(e instanceof HTMLElement))return;let n=e.getAttribute("tabindex");e.setAttribute("tabindex","-1"),e.focus({preventScroll:!0}),n!==null&&e.setAttribute("tabindex",n)}var Tt=class extends ge{constructor(e={}){super(),this.name="SwupA11yPlugin",this.requires={swup:">=4"},this.defaults={headingSelector:"h1",respectReducedMotion:!0,autofocus:!1,announcements:{visit:"Navigated to: {title}",url:"New page at {url}"}},this.options=void 0,this.announcer=void 0,this.announcementDelay=100,this.rootSelector="body",this.handleAnchorScroll=(n,{hash:r})=>{let i=this.swup.getAnchorElement(r);i instanceof HTMLElement&&xs(i)},this.options=jn({},this.defaults,e),this.announcer=new Wn}mount(){this.swup.hooks.create("content:announce"),this.swup.hooks.create("content:focus"),this.before("visit:start",this.prepareVisit),this.on("visit:start",this.markAsBusy),this.on("visit:end",this.unmarkAsBusy),this.on("visit:end",this.focusContent),this.on("visit:end",this.announceContent),this.on("scroll:anchor",this.handleAnchorScroll),this.before("visit:start",this.disableAnimations),this.before("link:self",this.disableAnimations),this.before("link:anchor",this.disableAnimations),this.swup.announce=this.announce.bind(this)}unmount(){this.swup.announce=void 0}async announce(e){await this.announcer.announce(e)}markAsBusy(){document.documentElement.setAttribute("aria-busy","true")}unmarkAsBusy(){document.documentElement.removeAttribute("aria-busy")}prepareVisit(e){e.a11y={announce:void 0,focus:this.rootSelector}}announceContent(e){this.swup.hooks.callSync("content:announce",e,void 0,n=>{n.a11y.announce===void 0&&(n.a11y.announce=this.getPageAnnouncement()),n.a11y.announce&&this.announcer.announce(n.a11y.announce,this.announcementDelay)})}focusContent(e){this.swup.hooks.callSync("content:focus",e,void 0,n=>{n.a11y.focus&&(this.options.autofocus&&function(){let r=function(){let i=document.querySelector("body [autofocus]");if(i&&!i.closest('[inert], [aria-disabled], [aria-hidden="true"]'))return i}();return!!r&&(r!==document.activeElement&&r.focus(),!0)}()===!0||xs(n.a11y.focus))})}getPageAnnouncement(){let{headingSelector:e,announcements:n}=this.options;return function({headingSelector:r="h1",announcements:i={}}){var s,o;let a=document.documentElement.lang||"*",{href:l,url:u,pathname:c}=I.fromUrl(window.location.href),d=(s=(o=i[a])!=null?o:i["*"])!=null?s:i;if(typeof d!="object")return;let h=document.querySelector(r);h||console.warn(`SwupA11yPlugin: No main heading (${r}) found on new page`);let p=h?.getAttribute("aria-label")||h?.textContent||document.title||Es(d.url,{href:l,url:u,path:c});return Es(d.visit,{title:p,href:l,url:u,path:c})}({headingSelector:e,announcements:n})}disableAnimations(e){this.options.respectReducedMotion&&window.matchMedia("(prefers-reduced-motion: reduce)").matches&&(e.animation.animate=!1,e.scroll.animate=!1)}};function zn(){return zn=Object.assign?Object.assign.bind():function(t){for(var e=1;e{let a=Math.random()*this.trickleValue;this.setValue(this.value+a)},e!==void 0&&(this.className=String(e)),n!==void 0&&(this.styleAttr=String(n)),r!==void 0&&(this.animationDuration=Number(r)),i!==void 0&&(this.minValue=Number(i)),s!==void 0&&(this.initialValue=Number(s)),o!==void 0&&(this.trickleValue=Number(o)),this.styleElement=this.createStyleElement(),this.progressElement=this.createProgressElement()}get defaultStyles(){return` + .${this.className} { + position: fixed; + display: block; + top: 0; + left: 0; + width: 100%; + height: 3px; + background-color: black; + z-index: 9999; + transition: + transform ${this.animationDuration}ms ease-out, + opacity ${this.animationDuration/2}ms ${this.animationDuration/2}ms ease-in; + transform: translate3d(0, 0, 0) scaleX(var(--progress, 0)); + transform-origin: 0; + } + `}show(){this.visible||(this.visible=!0,this.installStyleElement(),this.installProgressElement(),this.startTrickling())}hide(){this.visible&&!this.hiding&&(this.hiding=!0,this.fadeProgressElement(()=>{this.uninstallProgressElement(),this.stopTrickling(),this.visible=!1,this.hiding=!1}))}setValue(e){this.value=Math.min(1,Math.max(this.minValue,e)),this.refresh()}installStyleElement(){document.head.prepend(this.styleElement)}installProgressElement(){this.progressElement.style.setProperty("--progress",String(0)),this.progressElement.style.opacity="1",document.body.prepend(this.progressElement),this.progressElement.scrollTop=0,this.setValue(Math.random()*this.initialValue)}fadeProgressElement(e){this.progressElement.style.opacity="0",setTimeout(e,1.5*this.animationDuration)}uninstallProgressElement(){this.progressElement.remove()}startTrickling(){this.trickleInterval||(this.trickleInterval=window.setInterval(this.trickle,this.animationDuration))}stopTrickling(){window.clearInterval(this.trickleInterval),delete this.trickleInterval}refresh(){requestAnimationFrame(()=>{this.progressElement.style.setProperty("--progress",String(this.value))})}createStyleElement(){let e=document.createElement("style");return this.styleAttr.split(" ").forEach(n=>e.setAttribute(n,"")),e.textContent=this.defaultStyles,e}createProgressElement(){let e=document.createElement("div");return e.className=this.className,e.setAttribute("aria-hidden","true"),e}},_t=class extends ge{constructor(e={}){super(),this.name="SwupProgressPlugin",this.defaults={className:"swup-progress-bar",delay:300,transition:300,minValue:.1,initialValue:.25,finishAnimation:!0},this.options=void 0,this.progressBar=void 0,this.showProgressBarTimeout=void 0,this.hideProgressBarTimeout=void 0,this.options=zn({},this.defaults,e);let{className:n,minValue:r,initialValue:i,transition:s}=this.options;this.progressBar=new Gn({className:n,minValue:r,initialValue:i,animationDuration:s})}mount(){this.on("visit:start",this.startShowingProgress),this.on("page:view",this.stopShowingProgress)}startShowingProgress(){this.progressBar.setValue(0),this.showProgressBarAfterDelay()}stopShowingProgress(){this.progressBar.setValue(1),this.options.finishAnimation?this.finishAnimationAndHideProgressBar():this.hideProgressBar()}showProgressBar(){this.cancelHideProgressBarTimeout(),this.progressBar.show()}showProgressBarAfterDelay(){this.cancelShowProgressBarTimeout(),this.cancelHideProgressBarTimeout(),this.showProgressBarTimeout=window.setTimeout(this.showProgressBar.bind(this),this.options.delay)}hideProgressBar(){this.cancelShowProgressBarTimeout(),this.progressBar.hide()}finishAnimationAndHideProgressBar(){this.cancelShowProgressBarTimeout(),this.hideProgressBarTimeout=window.setTimeout(this.hideProgressBar.bind(this),this.options.transition)}cancelShowProgressBarTimeout(){window.clearTimeout(this.showProgressBarTimeout),delete this.showProgressBarTimeout}cancelHideProgressBarTimeout(){window.clearTimeout(this.hideProgressBarTimeout),delete this.hideProgressBarTimeout}};var ks=()=>{window.dispatchEvent(new Event("exdoc:loaded"))},Wu=(t,{page:e})=>{//i.test(e.html)&&(t.abort(),window.location.reload())};window.addEventListener("DOMContentLoaded",ks);!A&&window.location.protocol!=="file:"&&new Lt({animationSelector:!1,containers:["#main"],ignoreVisit:t=>{let e=t.split("#")[0];return e===window.location.pathname||e===window.location.pathname+".html"},linkSelector:'a[href]:not([href^="/"]):not([href^="http"])',hooks:{"page:load":Wu,"page:view":ks},plugins:[new Tt,new _t({delay:500})]});})(); +/*! Bundled license information: + +lunr/lunr.js: + (** + * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9 + * Copyright (C) 2020 Oliver Nightingale + * @license MIT + *) + (*! + * lunr.utils + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Set + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.tokenizer + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Pipeline + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Vector + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.stemmer + * Copyright (C) 2020 Oliver Nightingale + * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt + *) + (*! + * lunr.stopWordFilter + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.trimmer + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.TokenSet + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Index + * Copyright (C) 2020 Oliver Nightingale + *) + (*! + * lunr.Builder + * Copyright (C) 2020 Oliver Nightingale + *) +*/ diff --git a/site/dist/html-erlang-DQDXQC7W.css b/site/dist/html-erlang-DQDXQC7W.css new file mode 100644 index 00000000..2a7bf5fc --- /dev/null +++ b/site/dist/html-erlang-DQDXQC7W.css @@ -0,0 +1,6 @@ +:root{--main: hsl(0, 100%, 44%);--mainDark: hsl(0, 100%, 34%);--mainDarkest: hsl(0, 100%, 24%);--mainLight: hsl(0, 100%, 64%);--mainLightest: hsl(0, 100%, 74%);--searchBarFocusColor: hsl(0, 100%, 50%);--searchBarBorderColor: rgb(255, 71, 71, .1);--link-color: hsl(212, 96%, 45%);--link-visited-color: hsl(212, 96%, 40%)}body.dark{--link-color: hsl(212, 56%, 72%);--link-visited-color: hsl(212, 56%, 67%)}@font-face{font-family:Lato;font-style:normal;font-display:swap;font-weight:400;src:url(./lato-latin-ext-400-normal-N27NCBWW.woff2) format("woff2"),url(./lato-all-400-normal-MNITWADU.woff) format("woff");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Lato;font-style:normal;font-display:swap;font-weight:400;src:url(./lato-latin-400-normal-W7754I4D.woff2) format("woff2"),url(./lato-all-400-normal-MNITWADU.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Lato;font-style:normal;font-display:swap;font-weight:700;src:url(./lato-latin-ext-700-normal-Q2L5DVMW.woff2) format("woff2"),url(./lato-all-700-normal-XMT5XFBS.woff) format("woff");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Lato;font-style:normal;font-display:swap;font-weight:700;src:url(./lato-latin-700-normal-2XVSBPG4.woff2) format("woff2"),url(./lato-all-700-normal-XMT5XFBS.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}:root{--content-width: 949px;--content-gutter: 60px;--borderRadius-lg: 14px;--borderRadius-base: 8px;--borderRadius-sm: 3px;--navTabBorderWidth: 2px;--sansFontFamily: "Lato", system-ui, Segoe UI, Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";--monoFontFamily: ui-monospace, SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;--baseLineHeight: 1.5em;--gray25: hsl(207, 43%, 98%);--gray50: hsl(207, 43%, 96%);--gray100: hsl(212, 33%, 91%);--gray200: hsl(210, 29%, 88%);--gray300: hsl(210, 26%, 84%);--gray400: hsl(210, 21%, 64%);--gray450: hsl(210, 21%, 49%);--gray500: hsl(210, 21%, 34%);--gray600: hsl(210, 27%, 26%);--gray700: hsl(212, 35%, 17%);--gray750: hsl(214, 46%, 14%);--gray800: hsl(216, 52%, 11%);--gray800-opacity-0: hsla(216, 52%, 11%, 0%);--gray850: hsl(216, 63%, 8%);--gray900: hsl(218, 73%, 4%);--gray900-opacity-50: hsla(218, 73%, 4%, 50%);--gray900-opacity-0: hsla(218, 73%, 4%, 0%);--coldGrayFaint: hsl(240, 5%, 97%);--coldGrayLight: hsl(240, 5%, 88%);--coldGray-lightened-10: hsl(240, 5%, 56%);--coldGray: hsl(240, 5%, 46%);--coldGray-opacity-10: hsla(240, 5%, 46%, 10%);--coldGrayDark: hsl(240, 5%, 28%);--coldGrayDim: hsl(240, 5%, 18%);--yellowLight: hsl(43, 100%, 95%);--yellowDark: hsl(44, 100%, 15%);--yellow: hsl(60, 100%, 43%);--green-lightened-10: hsl(90, 100%, 45%);--green: hsl(90, 100%, 35%);--white: hsl(0, 0%, 100%);--white-opacity-50: hsla(0, 0%, 100%, 50%);--white-opacity-10: hsla(0, 0%, 100%, 10%);--white-opacity-0: hsla(0, 0%, 100%, 0%);--black: hsl(0, 0%, 0%);--black-opacity-10: hsla(0, 0%, 0%, 10%);--black-opacity-50: hsla(0, 0%, 0%, 50%);--orangeDark: hsl(30, 90%, 40%);--orangeLight: hsl(30, 80%, 50%);--text-xs: .75rem;--text-sm: .875rem;--text-md: 1rem;--text-lg: 1.125rem;--text-xl: 1.25rem;--transition-duration: .15s;--transition-timing: cubic-bezier(.4, 0, .2, 1);--transition-all: all var(--transition-duration) var(--transition-timing);--transition-colors: color var(--transition-duration) var(--transition-timing), background-color var(--transition-duration) var(--transition-timing), border-color var(--transition-duration) var(--transition-timing), text-decoration-color var(--transition-duration) var(--transition-timing), fill var(--transition-duration) var(--transition-timing), stroke var(--transition-duration) var(--transition-timing);--transition-opacity: opacity var(--transition-duration) var(--transition-timing)}@media screen and (max-width: 768px){:root{--content-width: 100%;--content-gutter: 20px}}option{background-color:var(--sidebarBackground)}:root{--background: var(--white);--contrast: var(--black);--textBody: var(--gray800);--textHeaders: var(--gray900);--textDetailAccent: var(--mainLight);--textDetailBackground: var(--coldGrayFaint);--iconAction: var(--coldGray);--iconActionHover: var(--gray800);--blockquoteBackground: var(--coldGrayFaint);--blockquoteBorder: var(--coldGrayLight);--tableHeadBorder: var(--gray100);--tableBodyBorder: var(--gray50);--warningBackground: hsl( 33, 100%, 97%);--warningHeadingBackground: hsl( 33, 87%, 64%);--warningHeading: var(--black);--errorBackground: hsl( 7, 81%, 96%);--errorHeadingBackground: hsl( 6, 80%, 60%);--errorHeading: var(--white);--infoBackground: hsl(206, 91%, 96%);--infoHeadingBackground: hsl(213, 92%, 62%);--infoHeading: var(--white);--neutralBackground: hsl(212, 29%, 92%);--neutralHeadingBackground: hsl(220, 43%, 11%);--neutralHeading: var(--white);--tipBackground: hsl(142, 31%, 93%);--tipHeadingBackground: hsl(134, 39%, 36%);--tipHeading: var(--white);--fnSpecAttr: var(--coldGray);--fnDeprecated: var(--yellowLight);--blink: var(--yellowLight);--codeBackground: var(--gray25);--codeBorder: var(--gray100);--codeScrollThumb: var(--gray400);--codeScrollBackground: var(--codeBorder);--admCodeBackground: var(--gray25);--admCodeBorder: var(--gray100);--admCodeColor: var(--black);--admInlineCodeColor: var(--black);--admInlineCodeBackground: var(--gray25);--admInlineCodeBorder: var(--gray100);--tabBorder: var(--gray300);--tabBorderTop: var(--gray100);--tabShadow: var(--gray25);--bottomActionsBtnBorder: var(--black-opacity-10);--bottomActionsBtnTitle: var(--mainDark);--modalBackground: var(--white);--settingsInput: var(--gray500);--settingsInputBackground: var(--white);--settingsInputBorder: var(--gray300);--settingsSectionBorder: var(--gray300);--quickSwitchInput: var(--gray500);--quickSwitchContour: var(--coldGray);--success: var(--green);--progressBarColor: var(--gray400);--sidebarAccentMain: var(--black);--sidebarBackground: var(--gray50);--sidebarHeader: var(--gray100);--sidebarMuted: var(--gray800);--sidebarHover: var(--black);--sidebarStaleVersion: var(--orangeDark);--sidebarSubheadings: var(--gray500);--sidebarItem: var(--black);--sidebarInactiveItemBorder: var(--gray500);--sidebarInactiveItemMarker: var(--gray200);--sidebarLanguageAccentBar: var(--mainDark);--sidebarActiveItem: var(--mainDarkest);--searchBarBorder: var(--gray200);--searchAccentMain: var(--gray600);--searchLanguageAccentBar: var(--main);--searchSearch: var(--white);--autocompleteBorder: rgba(3, 9, 19, .1);--autocompletePreview: var(--gray25);--autocompleteSelected: var(--gray25);--autocompleteHover: var(--gray50);--autocompleteBackground: var(--white);--suggestionBorder: var(--gray200);--autocompleteResults: var(--gray600);--autocompleteResultsBold: var(--gray800);--autocompleteLabelBack: var(--gray100);--autocompleteLabelFont: var(--gray600)}body.dark{--background: var(--gray900);--contrast: var(--white);--textBody: var(--gray200);--textHeaders: var(--gray100);--textDetailAccent: var(--mainLight);--textDetailBackground: var(--gray700);--iconAction: var(--coldGray-lightened-10);--iconActionHover: var(--white);--blockquoteBackground: var(--coldGray-opacity-10);--blockquoteBorder: var(--coldGrayDim);--tableHeadBorder: var(--gray600);--tableBodyBorder: var(--gray700);--warningBackground: hsla( 33, 30%, 60%, 10%);--warningHeadingBackground: hsla( 33, 66%, 35%, 80%);--warningHeading: var(--white);--errorBackground: hsla( 7, 30%, 60%, 10%);--errorHeadingBackground: hsla( 6, 70%, 40%, 80%);--errorHeading: var(--white);--infoBackground: hsla(206, 30%, 60%, 10%);--infoHeadingBackground: hsla(213, 55%, 35%, 80%);--infoHeading: var(--white);--neutralBackground: hsl(210, 30%, 60%, 10%);--neutralHeadingBackground: var(--gray600);--neutralHeading: var(--white);--tipBackground: hsla(142, 30%, 60%, 10%);--tipHeadingBackground: hsla(134, 45%, 30%, 80%);--tipHeading: var(--white);--fnSpecAttr: var(--gray400);--fnDeprecated: var(--yellowDark);--blink: var(--gray600);--codeBackground: var(--gray750);--codeBorder: var(--gray600);--codeScrollThumb: var(--gray500);--codeScrollBackground: var(--codeBorder);--admCodeBackground: var(--gray750);--admCodeBorder: var(--gray600);--admCodeColor: var(--gray100);--admInlineCodeColor: var(--gray100);--admInlineCodeBackground: var(--gray750);--admInlineCodeBorder: var(--gray600);--tabBorder: var(--gray700);--tabBorderTop: var(--gray700);--tabShadow: var(--black);--bottomActionsBtnBorder: var(--white-opacity-10);--bottomActionsBtnTitle: var(--mainLightest);--modalBackground: var(--gray800);--settingsInput: var(--white);--settingsInputBackground: var(--gray700);--settingsInputBorder: var(--gray700);--settingsSectionBorder: var(--gray700);--quickSwitchInput: var(--gray300);--quickSwitchContour: var(--gray500);--success: var(--green-lightened-10);--progressBarColor: var(--gray300);--sidebarAccentMain: var(--gray50);--sidebarBackground: var(--gray800);--sidebarHeader: var(--gray700);--sidebarMuted: var(--gray300);--sidebarHover: var(--white);--sidebarStaleVersion: var(--orangeLight);--sidebarSubheadings: var(--gray400);--sidebarItem: var(--gray200);--sidebarInactiveItemBorder: var(--gray400);--sidebarInactiveItemMarker: var(--gray600);--sidebarLanguageAccentBar: var(--mainLight);--sidebarActiveItem: var(--mainLightest);--searchBarBorder: var(--gray500);--searchAccentMain: var(--gray300);--searchSearch: var(--gray900);--autocompleteBorder: rgba(28,42,60,.75);--autocompletePreview: var(--gray750);--autocompleteSelected: var(--gray750);--autocompleteHover: var(--gray700);--autocompleteBackground: var(--gray800);--suggestionBorder: var(--gray600);--autocompleteResults: var(--gray200);--autocompleteResultsBold: var(--gray100);--autocompleteLabelBack: var(--gray600);--autocompleteLabelFont: rgba(255, 255, 255, .8)}:root:has(body.dark){color-scheme:dark}*,:before,:after{box-sizing:border-box}html{font-family:system-ui,Segoe UI,Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";line-height:1.15;-webkit-text-size-adjust:100%;tab-size:4}body{margin:0}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-color:currentcolor}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}legend{padding:0}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}@font-face{font-family:remixicon;src:url(./remixicon-QPNJX265.woff2) format("woff2");font-display:swap}[class^=ri-],[class*=" ri-"],.remix-icon{font-family:remixicon;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}:root{--icon-arrow-up-s: "\ea78";--icon-arrow-down-s: "\ea4e";--icon-arrow-right-s: "\ea6e";--icon-add: "\ea13";--icon-subtract: "\f1af";--icon-error-warning: "\eca1";--icon-external-link-line: "\ecaf";--icon-information: "\ee59";--icon-alert: "\ea21";--icon-double-quotes-l: "\ec51";--icon-link-m: "\eeaf";--icon-close-line: "\eb99";--icon-code-s-slash-line: "\ebad";--icon-menu-line: "\ef3e";--icon-search-2-line: "\f0cd";--icon-settings-3-line: "\f0e6";--icon-printer-line: "\f029"}.ri-lg{font-size:1.3333em;line-height:.75em;vertical-align:-.0667em}.ri-settings-3-line:before{content:var(--icon-settings-3-line)}.ri-add-line:before{content:var(--icon-add)}.ri-subtract-line:before{content:var(--icon-subtract)}.ri-arrow-up-s-line:before{content:var(--icon-arrow-up-s)}.ri-arrow-down-s-line:before{content:var(--icon-arrow-down-s)}.ri-arrow-right-s-line:before{content:var(--icon-arrow-right-s)}.ri-external-link-line:before{content:var(--icon-external-link-line)}.ri-search-2-line:before{content:var(--icon-search-2-line)}.ri-menu-line:before{content:var(--icon-menu-line)}.ri-close-line:before{content:var(--icon-close-line)}.ri-link-m:before{content:var(--icon-link-m)}.ri-code-s-slash-line:before{content:var(--icon-code-s-slash-line)}.ri-error-warning-line:before{content:var(--icon-error-warning)}.ri-information-line:before{content:var(--icon-information)}.ri-alert-line:before{content:var(--icon-alert)}.ri-double-quotes-l:before{content:var(--icon-double-quotes-l)}.ri-printer-line:before{content:var(--icon-printer-line)}html,body{box-sizing:border-box;height:100%;width:100%}body{--sidebarWidth: 300px;--sidebarMinWidth: 300px;--sidebarTransitionDuration: .3s;background-color:var(--background);color:var(--textBody);font-size:var(--text-md);line-height:1.6875em;outline:none!important}*,*:before,*:after{box-sizing:inherit}.body-wrapper{display:flex;height:100%}.sidebar{display:none;flex-direction:column;width:var(--sidebarWidth);min-width:var(--sidebarMinWidth);max-width:50vw;height:100%;position:fixed;top:0;left:calc(-1 * var(--sidebarWidth));z-index:100;resize:horizontal}.sidebar-button{padding:26px 12px 18px 19px;position:fixed;z-index:200;top:0;left:0;will-change:transform;transform:translate(0)}.content{left:0;width:100%;height:100%;position:absolute}.content .content-inner{container:content / inline-size;max-width:var(--content-width);min-height:100%;margin:0 auto;padding:0 var(--content-gutter) 10px}.content-inner:focus{outline:none}.sidebar-transition .sidebar,.sidebar-transition .sidebar-button,.sidebar-transition .content{transition:all var(--sidebarTransitionDuration) ease-in-out allow-discrete}.sidebar-open .sidebar,.sidebar-transition .sidebar{display:flex}.sidebar-open .sidebar{left:0}.sidebar-open .sidebar-button{transform:translate(calc(var(--sidebarWidth) - 100%))}.sidebar-open .content{width:calc(100% - var(--sidebarWidth));left:var(--sidebarWidth)}@media screen and (max-width: 768px){.sidebar-open .content{left:0;width:100%}.sidebar{max-width:90vw}body:not(.sidebar-open) .sidebar-button{position:absolute}}.swup-progress-bar{height:2px;background-color:var(--progressBarColor)}.sidebar{--sidebarFontSize: 16px;--sidebarLineHeight: 20px;font-family:var(--sansFontFamily);font-size:var(--sidebarFontSize);line-height:var(--sidebarLineHeight);background-color:var(--sidebarBackground);color:var(--sidebarAccentMain);overflow:hidden;& .sidebar-tabpanel{scrollbar-width:thin}}.apple-os .sidebar{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.sidebar ul{list-style:none}.sidebar ul li{margin:0;padding:0 10px}.sidebar a{color:var(--sidebarAccentMain);text-decoration:none;transition:var(--transition-colors)}.sidebar a:hover{color:var(--sidebarHover)}.sidebar .external-link{margin-left:2.5px}.sidebar .sidebar-header{background-color:var(--sidebarHeader);width:100%}.sidebar .sidebar-projectInfo{display:flex;justify-content:start;align-items:center;gap:8px;margin:12px 34px 12px 14px}.sidebar .sidebar-projectInfo>div{flex:1}.sidebar .sidebar-projectImage{align-self:flex-end}.sidebar .sidebar-projectImage img{display:block;max-width:48px;max-height:48px}.sidebar .sidebar-projectName{font-weight:700;font-size:var(--text-xl);line-height:24px;color:var(--sidebarAccentMain);margin:0;padding:0;word-wrap:break-word;display:block;width:calc(100% - 12px)}.sidebar .sidebar-projectVersion{display:block;position:relative;margin:0;padding:0;font-size:var(--sidebarFontSize);line-height:var(--sidebarLineHeight);color:var(--sidebarMuted);width:calc(100% - 12px)}.sidebar .sidebar-projectVersion form{display:flex}.sidebar .sidebar-projectVersion select{cursor:pointer;position:relative;margin:0;padding:0 0 0 10px;border:none;-webkit-appearance:none;appearance:none;background-color:transparent;color:var(--sidebarMuted);z-index:2}.sidebar .sidebar-projectVersion option{color:initial}.sidebar .sidebar-projectVersionsCaret{position:absolute;left:0;top:2px;z-index:1;font-size:8px;color:var(--sidebarMuted)}.sidebar .sidebar-projectVersion select::-ms-expand{display:none}.sidebar .sidebar-staleVersion{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--sidebarStaleVersion)}.sidebar .sidebar-staleVersion>a{color:var(--sidebarStaleVersion);font-weight:400}.sidebar .sidebar-staleIcon{font-size:var(--text-lg);position:relative;top:3px;line-height:0}.sidebar .sidebar-list-nav{display:flex;margin:0;padding:0;overflow:auto;scrollbar-width:thin}.sidebar .sidebar-list-nav :is(li,li button){text-transform:uppercase;letter-spacing:.02em;font-size:var(--text-sm);color:var(--sidebarSubheadings);white-space:nowrap}.sidebar .sidebar-list-nav li{display:inline-block;padding:0}.sidebar .sidebar-list-nav button{background:none;border:0;border-radius:0;-webkit-appearance:none;text-align:inherit;color:inherit;font-weight:inherit;cursor:pointer;display:inline-block;line-height:27px;padding:4px 14px;transition:var(--transition-all)}.sidebar .sidebar-list-nav button{border-bottom:var(--navTabBorderWidth) solid transparent}.sidebar .sidebar-list-nav button:not([aria-selected]):hover{border-bottom:var(--navTabBorderWidth) solid var(--sidebarInactiveItemBorder);color:var(--sidebarAccentMain);transition:var(--transition-all)}.sidebar .sidebar-list-nav button[aria-selected]{border-bottom:var(--navTabBorderWidth) solid var(--sidebarLanguageAccentBar);color:var(--sidebarAccentMain)}.sidebar .sidebar-tabpanel{flex:1 1 .01%;overflow-y:auto;overscroll-behavior:contain;position:relative;-webkit-overflow-scrolling:touch;padding-top:12px;scroll-padding-top:40px}.sidebar .full-list{margin:0;padding:0 0 20px;position:relative}.sidebar .full-list :is(li,a){display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.sidebar .full-list li{padding:0;line-height:27px}.sidebar .full-list li.group{text-transform:uppercase;font-weight:700;font-size:.8em;margin:1.5em 0 0;line-height:1.8em;color:var(--sidebarSubheadings);padding-left:15px}.sidebar .full-list li.nesting-context{font-weight:700;font-size:.9em;line-height:1.8em;color:var(--sidebarSubheadings);margin-top:10px;padding-left:15px}.sidebar .full-list a{margin-right:30px;padding:3px 0 3px 12px;border-left:var(--navTabBorderWidth) solid transparent;color:var(--sidebarItem)}.sidebar .full-list a[aria-selected]{color:var(--sidebarActiveItem)}.sidebar .full-list button{appearance:none;background-color:transparent;border:0;padding:0;cursor:pointer;color:inherit;width:20px;text-align:center;font-size:calc(1.2 * var(--sidebarFontSize));line-height:var(--sidebarLineHeight);position:absolute;display:block;right:10px;transform:translateY(-100%)}.sidebar .full-list a[aria-selected]+button{color:var(--sidebarActiveItem)}.sidebar .full-list button:after{font-family:remixicon;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;content:var(--icon-arrow-down-s)}.sidebar .full-list button[aria-expanded=true]:after{content:var(--icon-arrow-up-s)}.sidebar .full-list ul{display:none;margin:10px 0 10px 10px;padding:0}.sidebar .full-list button[aria-expanded=true]+ul{display:block}.sidebar .full-list>li>a{height:27px;line-height:var(--sidebarLineHeight)}.sidebar .full-list>li>a:hover{border-left-color:var(--sidebarLanguageAccentBar)}.sidebar .full-list>li>a[aria-selected]{border-left-color:var(--sidebarLanguageAccentBar)}.sidebar .full-list>li:last-child{margin-bottom:30px}.sidebar .full-list>li.group:first-child{margin-top:0}.sidebar .full-list>li>ul>li:not(:has(li a[aria-selected=true]))>a[aria-selected=true]:before,.sidebar .full-list>li>ul>li>a:hover:before{content:"\2022";position:absolute;margin-left:-15px;color:var(--sidebarActiveItem)}.sidebar .full-list ul li{line-height:var(--sidebarFontSize);padding:0 8px}.sidebar .full-list ul a{padding-left:15px;height:24px}.sidebar .full-list ul button{font-size:var(--sidebarFontSize)}.sidebar .full-list ul button:after{content:var(--icon-add)}.sidebar .full-list ul button[aria-expanded=true]:after{content:var(--icon-subtract)}.sidebar .full-list ul ul{margin:9px 0 9px 10px}.sidebar .full-list ul ul li{height:20px;color:var(--sidebarAccentMain)}.sidebar .full-list ul ul a{border-left:1px solid var(--sidebarInactiveItemMarker);padding:0 10px;height:20px}.sidebar .full-list ul ul a:hover{border-color:var(--sidebarLanguageAccentBar)}.sidebar .full-list ul ul a[aria-selected]{color:var(--sidebarActiveItem);border-color:var(--sidebarLanguageAccentBar)}.sidebar-button{cursor:pointer;background-color:transparent;border:none;font-size:var(--sidebarFontSize);color:var(--sidebarAccentMain)}.sidebar-button:hover{color:var(--sidebarHover)}body:not(.sidebar-open) .sidebar-button{color:var(--contrast)}@media screen and (max-height: 500px){.sidebar{overflow-y:auto}.sidebar .full-list{overflow:visible}}.top-search{background-color:var(--background);top:0;z-index:99;position:relative;width:100%;padding:10px 0}.search-settings{display:flex;column-gap:12px;align-items:center;width:100%;position:relative}.search-bar{border:1px solid var(--searchBarBorder);border-radius:var(--borderRadius-base);height:48px;position:relative;width:100%}.top-search .search-bar .search-input{background-color:var(--searchSearch);border:1px solid transparent;border-radius:var(--borderRadius-base);color:var(--searchAccentMain);position:relative;height:46px;padding:8px 35px 8px 43px;width:100%;transition:var(--transition-all)}.top-search .search-bar .search-input::placeholder{color:var(--searchAccentMain);opacity:.5}.top-search .search-bar .search-input:focus{border:1px solid var(--searchBarFocusColor);border-radius:calc(var(--borderRadius-base) - 1px);position:relative;box-shadow:0 4px 20px 0 var(--searchBarBorderColor) inset}.top-search .search-bar .search-label{position:relative}.top-search .search-bar .search-button{font-size:var(--text-sm);color:var(--searchAccentMain);background-color:transparent;border:none;cursor:pointer;left:11px;opacity:.5;padding:5px 1px 5px 5px;position:absolute;top:60%;transform:translateY(-60%);z-index:99;transition:var(--transition-all)}.top-search .search-bar.selected .search-button,.top-search .search-bar .search-button:hover,.top-search .search-bar .search-button:focus{color:var(--top-searchLanguageAccentBar);opacity:1}.top-search .search-bar .search-close-button{font-size:var(--text-md);color:var(--searchAccentMain);background-color:transparent;border:none;cursor:pointer;right:11px;margin:0;opacity:.5;padding:5px 1px 5px 0;position:absolute;transform:scaleY(0);top:calc(50% - 13px);transition:var(--transition-all);z-index:99}.top-search .search-bar .search-close-button:hover{opacity:.7}.top-search .search-settings button.icon-settings{display:flex;align-items:center;justify-content:flex-end}.top-search .search-settings .icon-settings{font-size:var(--text-xl);float:right;color:var(--iconAction);text-decoration:none;border:none;transition:color .3s ease-in-out;background-color:transparent;cursor:pointer;padding:0}.top-search .search-settings .icon-settings:hover{color:var(--iconActionHover)}.top-search .search-settings .icon-settings:visited{color:var(--iconAction)}@media screen and (max-width: 768px){.top-search{padding-left:calc(var(--content-gutter) + 36px);padding-right:var(--content-gutter);margin-left:calc(-1 * var(--content-gutter));margin-right:calc(-1 * var(--content-gutter));width:calc(2 * var(--content-gutter) + 100%)}.search-settings{width:100%;box-sizing:border-box}}body.search-focused .search-bar .search-close-button{transform:scaleY(1);transition:var(--transition-all)}@media screen and (hover: hover){body.search-focused .top-search{position:sticky!important}body.search-focused .sidebar-button{position:fixed!important}}@media screen and (hover: none){body.scroll-sticky .top-search{position:sticky!important}body.scroll-sticky .sidebar-button{position:fixed!important}}*:focus,button:focus,[type=button]:focus,[type=reset]:focus,[type=submit]:focus{outline:2px solid var(--main);outline-offset:-2px}*:focus:not(:focus-visible),button:focus:not(:focus-visible),[type=button]:focus:not(:focus-visible),[type=reset]:focus:not(:focus-visible),[type=submit]:focus:not(:focus-visible){outline:0}input[type=text],input[type=number],input[type=date],input[type=datetime],input[type=datetime-local],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=time],input[type=url],input[type=week],textarea{outline:0}.content-inner{font-size:1em;line-height:1.6875em;position:relative;background-color:var(--background);color:var(--textBody)}.content-inner .heading-with-actions{display:flex;flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:6px}.content-inner .heading-with-actions>*:not(h1){flex-shrink:0}.content-inner .heading-with-actions h1{flex-grow:1;justify-self:flex-start;max-width:100%;margin:0;overflow-wrap:break-word}.content-inner .heading-with-actions .icon-action{width:20px;height:20px;display:flex;justify-content:center;align-items:center;font-weight:400}.content-inner .heading-with-actions.top-heading .icon-action{font-size:1.2rem}@container content (width > 600px){.content-inner .heading-with-actions.top-heading{flex-wrap:nowrap;align-items:flex-start;& h1{padding-right:32px}& .icon-action{padding-top:1.7rem}}}.content-inner .top-heading{padding-top:1rem}.content-inner :is(h1,h2,h3,h4,h5,h6){font-family:var(--sansFontFamily);font-weight:700;line-height:1.5em;word-wrap:break-word;color:var(--textHeaders)}.content-inner h1{font-size:2em;margin:.5em 0}.content-inner h1.section-heading{margin:1.5em 0 .5em}.content-inner h1 small{font-weight:400}.content-inner h2{font-size:1.6em;padding-top:1em;margin-bottom:.5em}.content-inner h3{font-size:1.375em;margin:1em 0 .5em}.content-inner li+li{margin-top:.25em}.content-inner :is(a,.a-main){color:var(--link-color);text-decoration:underline;text-decoration-skip-ink:auto}.content-inner :is(a:visited,.a-main:visited){color:var(--link-visited-color)}.content-inner .icon-action{color:var(--iconAction);text-decoration:none;border:none;transition:var(--transition-colors);background-color:transparent;cursor:pointer}.content-inner .icon-action:hover{color:var(--iconActionHover)}.content-inner .icon-action:visited{color:var(--iconAction)}.content-inner .livebook-badge-container{display:flex}.content-inner a.livebook-badge{display:inline-flex}.content-inner .note{color:var(--iconAction);font-size:var(--text-xs);font-weight:400}.content-inner blockquote,.content-inner section.admonition{border-left:3px solid var(--blockquoteBorder);position:relative;margin:1.5625em 0;padding:0 1.2rem;overflow:auto;background-color:var(--blockquoteBackground);border-radius:var(--borderRadius-base)}.content-inner blockquote p:last-child,.content-inner section.admonition p:last-child{padding-bottom:1em;margin-bottom:0}.content-inner table{margin:2em 0;border-collapse:collapse;display:block;overflow:auto}.content-inner th{text-align:left;font-family:var(--sansFontFamily);font-weight:700;padding-bottom:.5em;white-space:nowrap}.content-inner thead tr{border-bottom:1px solid var(--tableHeadBorder)}.content-inner tbody tr{border-bottom:1px solid var(--tableBodyBorder)}.content-inner tbody tr:last-child{border-bottom:none}.content-inner tr{vertical-align:bottom;height:2.5em}.content-inner :is(td,th){padding:.25em .25em .25em 1em;line-height:2em;vertical-align:top}.content-inner .section-heading{--icon-size: 16px;--icon-spacing: 5px;display:grid;grid-template:1fr / 1fr}@media screen and (max-width: 768px){.content-inner .section-heading{--icon-spacing: 2px}}.content-inner .section-heading>:is(.hover-link,.text){grid-row:1;grid-column:1}.content-inner .section-heading .hover-link{text-decoration:none}.content-inner .section-heading i{font-size:var(--icon-size);color:var(--mainLight);top:-2px;margin-left:calc(-1 * (var(--icon-size) + var(--icon-spacing)));padding-right:var(--icon-spacing);position:relative;opacity:0}.content-inner :is(blockquote,section.admonition) .section-heading i{display:none}.content-inner .section-heading:is(:hover,:focus,:target) i{opacity:1}.content-inner .app-vsn{display:none!important;font-size:.6em;line-height:1.5em}@media screen and (max-width: 768px){.content-inner .app-vsn{display:block!important}}.content-inner img{max-width:100%}.content-inner strong>code{font-weight:700}.content-inner code{font-family:var(--monoFontFamily);font-style:normal;line-height:24px;font-weight:400;font-size:var(--text-sm)}@media screen and (max-width: 768px){.content-inner :is(ol,ul){padding-left:calc(1.5 * var(--content-gutter))}}.content-inner section.admonition{border-radius:var(--borderRadius-base);border-left:0}.content-inner section.admonition.warning{background-color:var(--warningBackground)}.content-inner section.admonition.error{background-color:var(--errorBackground)}.content-inner section.admonition.info{background-color:var(--infoBackground)}.content-inner section.admonition.neutral{background-color:var(--neutralBackground)}.content-inner section.admonition.tip{background-color:var(--tipBackground)}.content-inner section.admonition>.admonition-title{color:var(--contrast);margin:0 -1.2rem;padding:.7rem 1.2rem .7rem 3.3rem;font-weight:700;font-style:normal}.content-inner section.admonition>.admonition-title:before{color:var(--contrast);position:absolute;left:1rem;font-size:1.8rem;font-family:remixicon;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.content-inner section.admonition>.admonition-title.warning{background-color:var(--warningHeadingBackground);color:var(--warningHeading)}.content-inner section.admonition>.admonition-title.warning:before{content:var(--icon-error-warning);color:var(--warningHeading)}.content-inner section.admonition>.admonition-title.error{background-color:var(--errorHeadingBackground);color:var(--errorHeading)}.content-inner section.admonition>.admonition-title.error:before{content:var(--icon-error-warning);color:var(--errorHeading)}.content-inner section.admonition>.admonition-title.info{background-color:var(--infoHeadingBackground);color:var(--infoHeading)}.content-inner section.admonition>.admonition-title.info:before{content:var(--icon-information);color:var(--infoHeading)}.content-inner section.admonition>.admonition-title.neutral{background-color:var(--neutralHeadingBackground);color:var(--neutralHeading)}.content-inner section.admonition>.admonition-title.neutral:before{content:var(--icon-double-quotes-l);color:var(--neutralHeading)}.content-inner section.admonition>.admonition-title.tip{background-color:var(--tipHeadingBackground);color:var(--tipHeading)}.content-inner section.admonition>.admonition-title.tip:before{content:var(--icon-information);color:var(--tipHeading)}.content-inner section.admonition>.admonition-title code{margin:0 .5ch}.content-inner section.admonition code{background-color:var(--admInlineCodeBackground);border:1px solid var(--admInlineCodeBorder);color:var(--admInlineCodeColor)}.content-inner section.admonition pre code{background-color:var(--admCodeBackground);border:1px solid var(--admCodeBorder);color:var(--admCodeColor)}.content-inner section.admonition>.admonition-title :is(a,a:visited){color:inherit;text-decoration-color:currentColor}@media screen and (max-width: 768px){.content-inner section.admonition{margin-left:calc(-1 * var(--content-gutter));margin-right:calc(-1 * var(--content-gutter));padding-left:var(--content-gutter);padding-right:var(--content-gutter);border-radius:0}.content-inner section.admonition>.admonition-title{margin:0 calc(-1 * var(--content-gutter))}}.content-inner .summary h2 a{text-decoration:none;border:none;color:var(--textHeaders)!important}.content-inner .summary span.deprecated{color:var(--darkDeprecated);font-weight:400}.content-inner .summary .summary-row .summary-signature{font-family:var(--monoFontFamily);font-size:13px;font-weight:700}.content-inner .summary .summary-row .summary-signature a{text-decoration:none;border:none}.content-inner .summary .summary-row .summary-synopsis{padding:0 1.2em;margin:0 0 .5em}.content-inner .summary .summary-row .summary-synopsis p{margin:0;padding:0}@font-face{font-family:Consolas;src:local("Consolas");size-adjust:110%}.content-inner.content-inner :is(a:has(code,img),pre a){color:var(--link-color);text-shadow:none;text-decoration:none;background-image:none}.content-inner.content-inner :is(a:has(code,img),pre a):is(:visited,:active,:focus,:hover){color:var(--link-visited-color)}.content-inner code{background-color:var(--codeBackground);vertical-align:baseline;border-radius:var(--borderRadius-sm);padding:.1em .2em;border:1px solid var(--codeBorder);text-transform:none}.content-inner code.inline{border-radius:var(--borderRadius-sm);word-wrap:break-word}.content-inner pre{margin:var(--baseLineHeight) 0}.content-inner pre code{display:block;overflow-x:auto;white-space:inherit;padding:1em;scrollbar-width:thin}.content-inner pre code.output{margin:0 12px;max-height:400px;overflow:auto}.content-inner pre code.output+.copy-button{margin-right:12px}.content-inner pre code.output:before{content:"Output";display:block;position:absolute;top:-16px;left:12px;padding:2px 4px;font-size:var(--text-xs);font-family:var(--monoFontFamily);line-height:1;color:var(--textHeaders);background-color:var(--codeBackground);border:1px solid var(--codeBorder);border-bottom:0;border-radius:2px}@media screen and (max-width: 768px){.content-inner>pre:has(code),.content-inner section>pre:has(code){margin-left:calc(-1 * var(--content-gutter));margin-right:calc(-1 * var(--content-gutter))}.content-inner>pre code,.content-inner section>pre code{padding-left:var(--content-gutter);padding-right:var(--content-gutter);border-radius:0;border-left-width:0;border-right-width:0}}@keyframes blink-background{0%,to{background-color:var(--textDetailBackground)}50%{background-color:var(--blink)}}.content-inner .detail:target .detail-header{animation-duration:.55s;animation-name:blink-background;animation-iteration-count:1;animation-timing-function:ease-in-out}.content-inner .detail-header{margin:1em 0;padding:.5em .85em .5em 1em;background-color:var(--textDetailBackground);border-left:3px solid var(--textDetailAccent);font-size:1em;font-family:var(--monoFontFamily);position:relative}.content-inner .detail-header .signature{font-family:var(--monoFontFamily);font-size:13px;font-weight:700;line-height:2em}.content-inner .detail-header:hover a.detail-link,.content-inner .detail-header a.detail-link:focus{opacity:1;text-decoration:none}.content-inner .detail-header a.detail-link{transition:var(--transition-opacity);position:absolute;top:0;left:0;display:block;opacity:0;padding:.6em;line-height:1.5em;margin-left:-2.5em;text-decoration:none;border:none}@media screen and (max-width: 768px){.content-inner .detail-header a.detail-link{margin-left:-30px}}.content-inner .specs pre{font-family:var(--monoFontFamily);font-size:var(--text-xs);font-style:normal;line-height:24px;white-space:pre-wrap;margin:0;padding:0}.content-inner .specs .attribute{color:var(--fnSpecAttr)}.content-inner .docstring{margin:1.2em 0 3em 1.2em}@media screen and (max-width: 768px){.content-inner .docstring{margin-left:0}}.content-inner .docstring:is(h2,h3,h4,h5){font-weight:700}.content-inner .docstring h2{font-size:1.1em}.content-inner .docstring h3{font-size:1em}.content-inner .docstring h4{font-size:.95em}.content-inner .docstring h5{font-size:.9em}.content-inner div.deprecated{display:block;padding:1em;background-color:var(--fnDeprecated);border-radius:var(--borderRadius-sm);margin:var(--baseLineHeight) 0}.content-inner .footer{margin:4em auto 1em;text-align:center;font-size:var(--text-sm)}.content-inner .footer .line{display:inline-block}.content-inner .footer .footer-button{background-color:transparent;border:0;cursor:pointer;padding:0 4px}.content-inner .footer .footer-hex-package{margin-right:4px}.content-inner .bottom-actions{display:flex;justify-content:space-between;margin-top:4em;gap:12px}.bottom-actions-item{flex:1 1 0%}.content-inner .bottom-actions .bottom-actions-button{display:flex;text-decoration:none;flex-direction:column;border-radius:var(--borderRadius-sm);border:1px solid var(--bottomActionsBtnBorder);padding:12px 16px;min-width:150px;transition:var(--transition-all)}.content-inner .bottom-actions .bottom-actions-button:hover{border-color:var(--mainLight)}.content-inner .bottom-actions .bottom-actions-button .subheader{font-size:.8em;color:var(--textHeaders);white-space:nowrap}.content-inner .bottom-actions .bottom-actions-button .title{color:var(--bottomActionsBtnTitle)}.content-inner .bottom-actions .bottom-actions-button[rel=prev]{text-align:start}.content-inner .bottom-actions .bottom-actions-button[rel=next]{text-align:end}@media screen and (max-width: 768px){.content-inner .bottom-actions{flex-direction:column-reverse}}.page-cheatmd .content-inner{--horizontal-space: 1.5em;--vertical-space: 1em}@media (max-width: 600px){.page-cheatmd .content-inner{--horizontal-space: 1em;--vertical-space: .75em}}.page-cheatmd .content-inner{max-width:1200px}.page-cheatmd .content-inner h1{margin-bottom:var(--vertical-space)}.page-cheatmd .content-inner h2{margin:var(--vertical-space) 0;column-span:all;color:var(--gray700);font-weight:500}.dark .page-cheatmd .content-inner h2{color:var(--gray200)}.page-cheatmd .content-inner h3{margin:0 0 1em;font-weight:400}.page-cheatmd .content-inner section.h3{min-width:300px;margin:0;padding:0 0 calc(var(--vertical-space) * 2) 0;break-inside:avoid}.page-cheatmd .content-inner h3 .text{overflow:hidden}.page-cheatmd .content-inner h3 .text:after{content:"";margin-left:calc(var(--horizontal-space) / 2);vertical-align:baseline;display:inline-block;width:100%;height:1px;margin-right:-100%;margin-bottom:5px;background-color:var(--codeBorder)}.page-cheatmd .content-inner h4{display:block;margin:0;padding:.25em var(--horizontal-space);font-weight:400;background:var(--gray100);color:#567;border:solid 1px 1px 0 1px var(--gray100)}.dark .page-cheatmd .content-inner h4{background:#192f50;color:var(--textBody);border:1px solid #192f50;border-bottom:0}.page-cheatmd .content-inner .h2 p{margin:0;display:block;background:var(--gray50);padding:var(--vertical-space) var(--horizontal-space)}.dark .page-cheatmd .content-inner .h2 p{background:var(--gray700)}.page-cheatmd .content-inner .h2 p>code{color:#eb5757;border-radius:var(--borderRadius-sm);padding:.2em .4em}.page-cheatmd .content-inner pre code{padding:var(--vertical-space) var(--horizontal-space)}.page-cheatmd .content-inner .h2 pre{margin:0}.page-cheatmd .content-inner .h2 pre+pre{margin-top:-1px}.page-cheatmd .content-inner pre.wrap{white-space:break-spaces}@media screen and (max-width: 768px){.page-cheatmd .content-inner pre code{border-left-width:1px!important;border-right-width:1px!important}}.page-cheatmd .content-inner .h2 table{display:table;box-sizing:border-box;width:100%;border-collapse:collapse;margin:0}.page-cheatmd .content-inner .h2 th{padding:var(--vertical-space) var(--horizontal-space);line-height:inherit;margin-bottom:-1px;vertical-align:middle;border-bottom:1px solid var(--codeBorder)}.page-cheatmd .content-inner .h2 td{padding:var(--vertical-space) var(--horizontal-space);border:0;border-bottom:1px solid var(--codeBorder)}.page-cheatmd .content-inner .h2 tr:first-child{border-top:1px solid var(--codeBorder)}.page-cheatmd .content-inner .h2 td code{color:#eb5757;border-radius:var(--borderRadius-sm);padding:.2em .4em}.page-cheatmd .content-inner .h2 thead{background-color:var(--gray50)}.dark .page-cheatmd .content-inner .h2 thead{background-color:var(--gray700)}.page-cheatmd .content-inner .h2 tbody{background-color:var(--codeBackground)}.page-cheatmd .content-inner .h2 :is(ul,ol){margin:0;padding:0}.page-cheatmd .content-inner .h2 li{list-style-position:inside;padding:.5em var(--horizontal-space);line-height:2em;vertical-align:middle;background-color:var(--codeBackground);border-bottom:1px solid var(--codeBorder);margin-top:0}.page-cheatmd .content-inner .h2 :is(ul,ol)+pre code{border-top:0}.page-cheatmd .content-inner .h2 li>code{color:#eb5757;border-radius:var(--borderRadius-sm);padding:.2em .4em}.page-cheatmd .content-inner section.width-50{display:block;width:50%;margin:0}.page-cheatmd .content-inner section.width-50>section>table{width:100%}.page-cheatmd .content-inner section:is(.col-2,.col-2-left,.col-3){column-gap:40px}.page-cheatmd .content-inner section.col-2{column-count:2;height:auto}.page-cheatmd .content-inner section.col-2-left{display:grid;grid-template-columns:calc(100% / 3) auto}.page-cheatmd .content-inner section.col-2-left>h2{grid-column-end:span 2}.page-cheatmd .content-inner section.col-3{column-count:3;height:auto}.page-cheatmd .content-inner section.list-4>ul{display:flex;flex-wrap:wrap}.page-cheatmd .content-inner section.list-4>ul>li{flex:0 0 25%}.page-cheatmd .content-inner section.list-6>ul{display:flex;flex-wrap:wrap}.page-cheatmd .content-inner section.list-6>ul>li{flex:0 0 calc(100% / 6)}@media screen and (max-width: 1400px){.page-cheatmd .content-inner section.col-3{column-count:2}.page-cheatmd .content-inner section.col-2-left{display:flex;flex-direction:column}}@media screen and (max-width: 1200px){.page-cheatmd .content-inner section:is(.col-2,.col-3){display:flex;flex-direction:column}.page-cheatmd .content-inner section.list-6>ul>li{flex:0 0 25%}}@media screen and (max-width: 1000px){.page-cheatmd .content-inner section:is(.list-4,.list-6)>ul>li{flex:0 0 calc(100% / 3)}}@media screen and (max-width: 600px){.page-cheatmd .content-inner section:is(.list-4,.list-6)>ul>li{flex:0 0 50%}.page-cheatmd .content-inner section.width-50{width:100%}}#search{min-height:200px;position:relative}#search .loading{height:64px;width:64px;position:absolute;top:50%;left:calc(50% - 32px)}#search .loading div{box-sizing:border-box;display:block;position:absolute;width:51px;height:51px;margin:6px;border:6px solid var(--coldGray);border-radius:50%;animation:loading 1.2s cubic-bezier(.5,0,.5,1) infinite;border-color:var(--coldGray) transparent transparent transparent}#search .loading div:nth-child(1){animation-delay:-.45s}#search .loading div:nth-child(2){animation-delay:-.3s}#search .loading div:nth-child(3){animation-delay:-.15s}@keyframes loading{0%{transform:rotate(0)}to{transform:rotate(360deg)}}#search .result{margin:2em 0 2.5em}#search .result p{margin:0}#search .result-id{font-size:1.4em;margin:0}#search .result-id a{text-decoration:none;color:var(--textHeaders);transition:var(--transition-colors)}#search .result-id a:is(:visited,:active){color:var(--textHeaders)}#search .result-id a:is(:hover,:focus){color:var(--main)}#search :is(.result-id,.result-elem) em{font-style:normal;color:var(--main)}#search .result-id small{font-weight:400}@keyframes keyboard-shortcuts-show{0%{opacity:0}to{opacity:1}}.modal{animation-duration:.15s;animation-name:keyboard-shortcuts-show;animation-iteration-count:1;animation-timing-function:ease-in-out;display:none;background-color:#000000bf;position:fixed;inset:0;z-index:300}.modal.shown{display:block}.modal .modal-contents{margin:75px auto 0;max-width:500px;background-color:var(--modalBackground);border-radius:var(--borderRadius-sm);box-shadow:2px 2px 8px #0003;padding:25px 35px 35px}@media screen and (max-width: 768px){.modal .modal-contents{padding:20px}}.modal .modal-header{display:flex;align-items:start}.modal .modal-title{display:inline-block;flex-grow:1;font-size:1.2rem;font-weight:700;margin-bottom:20px}.modal .modal-title button{border:none;background-color:transparent;color:var(--textHeaders);font-weight:700;margin-right:30px;padding-left:0;text-align:left;transition:var(--transition-colors)}.modal .modal-title button:hover{color:var(--main);cursor:pointer}.modal .modal-title button.active{color:var(--main)}.modal .modal-close{cursor:pointer;display:block;font-size:1.5rem;margin:-8px -8px 0 0;padding:8px;opacity:.7;background-color:transparent;color:var(--textHeaders);border:none;transition:var(--transition-opacity)}.modal .modal-close:hover{opacity:1}#keyboard-shortcuts-content dl.shortcut-row{display:flex;align-items:center;justify-content:space-between;margin:0;padding:6px 0 8px;border-bottom:1px solid var(--settingsSectionBorder)}#keyboard-shortcuts-content dl.shortcut-row:last-of-type{border-bottom-style:none}#keyboard-shortcuts-content dl.shortcut-row:first-child{padding-top:0}#keyboard-shortcuts-content :is(.shortcut-keys,.shortcut-description){display:inline-block}#keyboard-shortcuts-content kbd>kbd{background-color:var(--settingsInputBorder);color:var(--contrast);border-radius:var(--borderRadius-sm);font-family:inherit;font-weight:700;display:inline-block;line-height:1;padding:4px 7px 6px;min-width:26px;text-align:center;font-size:var(--text-sm)}#keyboard-shortcuts-content :is(.shortcut-keys,.shortcut-description){margin:0}#quick-switch-modal-body{width:100%;position:relative}#quick-switch-modal-body .ri-search-2-line{position:absolute;left:0;top:0;padding:4px 10px;color:var(--quickSwitchContour);font-weight:700}#quick-switch-modal-body #quick-switch-input{width:100%;padding:8px 6px 8px 38px;border:none;color:var(--quickSwitchInput);background-color:transparent;border-bottom:1px solid var(--quickSwitchContour);box-sizing:border-box;transition:all .12s ease-out}#quick-switch-modal-body #quick-switch-results{margin:0}#quick-switch-modal-body .quick-switch-result{padding:2px 5px;border-bottom:1px dotted var(--quickSwitchContour);transition:all .12s ease-out}#quick-switch-modal-body .quick-switch-result:last-child{border-bottom:none}#quick-switch-modal-body .quick-switch-result:hover{cursor:pointer}#quick-switch-modal-body .quick-switch-result:is(:hover,.selected){border-left:4px solid var(--main);background-color:var(--codeBackground)}.autocomplete{display:none;position:absolute;width:calc(100% - 32px);top:55px}.autocomplete .triangle{width:0;height:0;border-left:12px solid transparent;border-right:12px solid transparent;border-bottom:12px solid var(--autocompleteBackground);position:absolute;top:8px;left:26px;transform:translate(-50%);z-index:100;background-color:transparent}.autocomplete-preview{width:100%;margin:0;height:100%;line-height:20px;background-color:var(--background);font-family:var(--sansFontFamily);border:4px solid var(--autocompleteBorder);padding:12px 16px}.autocomplete-preview div,.autocomplete-preview span{display:none}.autocomplete-preview.loading div{float:left;display:block;border:5px solid var(--autocompleteBorder);border-radius:50%;border-top:5px solid var(--textDetailAccent);width:20px;height:20px;animation:spinner 4s linear infinite}.autocomplete-preview.loading span{color:var(--autocompleteResults);display:inline;margin-left:6px}.autocomplete-preview.loading span:after{color:var(--autocompleteResults);content:"Loading"}@keyframes spinner{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.autocomplete-preview.loading iframe{height:0}.autocomplete-preview iframe{width:100%;height:100%;border:0}.autocomplete-results{list-style:none;margin:0;padding:15px 20px;display:flex;flex-wrap:wrap;justify-content:space-between;gap:8px;color:var(--autocompleteResults);font-family:var(--sansFontFamily);font-weight:300;font-size:.9rem}.autocomplete-results .query{margin-right:auto}.autocomplete-results .bold{color:var(--autocompleteResultsBold);font-weight:400}.autocomplete.shown{display:block}.autocomplete-container{position:absolute;top:15px;width:100%;z-index:200}.autocomplete-suggestions{background-color:var(--autocompleteBackground);border-radius:var(--borderRadius-base);box-shadow:0 15px 99px 0 var(--autocompleteBorder);overflow-y:auto;max-height:450px;white-space:normal;overflow-x:hidden;overscroll-behavior-y:contain;scrollbar-width:thin}.autocomplete-suggestions.previewing:has(.selected){max-height:80vh}.autocomplete-suggestions.previewing:has(.selected) .autocomplete-suggestion:not(.selected){display:none}.autocomplete-suggestions.previewing:not(:has(.selected)) .autocomplete-preview{display:none}.autocomplete-suggestions:not(.previewing) .autocomplete-preview{display:none}.autocomplete-suggestion{color:var(--textHeaders)!important;display:block;padding:12px 20px;text-decoration:none!important;transition:var(--transition-colors);border-top:1px solid var(--suggestionBorder);font-size:.9rem}.autocomplete-suggestion.selected{background-color:var(--autocompleteSelected);box-shadow:inset 2px 0 var(--main)}.autocomplete-suggestion:hover{background-color:var(--autocompleteHover)}.autocomplete-suggestion:not(.selected) .autocomplete-preview-indicator{display:none}.autocomplete-preview-indicator{float:right}.autocomplete-preview-indicator button{color:var(--iconAction);display:flex;align-items:center;text-decoration:none;border:1px solid var(--suggestionBorder);border-radius:var(--borderRadius-base);transition:var(--transition-colors);background-color:var(--autocompletePreview);cursor:pointer;padding:4px 8px;font-size:var(--text-sm)}.autocomplete-preview-indicator button:hover{color:var(--iconActionHover);background-color:var(--autocompleteHover)}.autocomplete-preview-indicator button i{margin-right:4px}.autocomplete-suggestions.previewing .autocomplete-preview-indicator-closed{display:none}.autocomplete-suggestions:not(.previewing) .autocomplete-preview-indicator-open{display:none}.autocomplete-suggestion:hover:not(.selected) .autocomplete-preview-indicator-closed{display:block}.autocomplete-suggestion em{font-style:normal;font-weight:700}.autocomplete-suggestion .description{opacity:.6;padding-top:3px}.autocomplete-suggestion .label{background-color:var(--autocompleteLabelBack);opacity:.6;color:var(--autocompleteLabelFont);padding:4px 8px;border-radius:4px;margin-left:5px;text-transform:uppercase;font-family:var(--sansFontFamily);font-size:.7rem}.autocomplete-suggestion .header{margin-right:5px}.autocomplete-suggestion .title,.autocomplete-suggestion .description{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:100%}@media screen and (hover: none){.autocomplete-preview-indicator,.autocomplete-results .press-return{display:none!important}}.tooltip{box-shadow:0 0 10px var(--black-opacity-10);max-height:300px;max-width:500px;padding:0;position:absolute;pointer-events:none;margin:0;z-index:99;top:0;left:0;visibility:hidden;transform:translateY(20px);opacity:0;transition:.2s visibility ease-out,.2s transform ease-out,.2s opacity ease-out}.tooltip.tooltip-shown{visibility:visible;transform:translateY(0);opacity:1}.tooltip .tooltip-body{border:1px solid var(--codeBorder);border-radius:var(--borderRadius-sm);overflow:auto}.tooltip .tooltip-body .signature{min-width:320px;width:100%;line-height:1em}.tooltip .tooltip-body .detail-header{border-left:0;margin-bottom:0;margin-top:0}.tooltip .tooltip-body .docstring{background-color:var(--background);padding:1.2em;margin:0;width:498px}.tooltip .tooltip-body .docstring-plain{max-width:498px;width:auto}.tooltip .tooltip-body .version-info{float:right;font-family:var(--monoFontFamily);font-weight:400;opacity:.3;padding-left:.3em}pre{position:relative}pre:hover .copy-button,pre .copy-button:focus{opacity:1}.copy-button{display:flex;opacity:0;position:absolute;top:7px;right:8px;padding:8px;background-color:transparent;backdrop-filter:blur(8px);border-radius:var(--borderRadius-sm);border:1px solid var(--codeBorder);cursor:pointer;transition:var(--transition-all);font-size:var(--text-sm);line-height:24px;color:currentColor;& svg[aria-live=polite]{display:none}}.copy-button svg{opacity:.5;transition:var(--transition-all)}pre .copy-button:hover svg,pre .copy-button:focus-visible svg{opacity:1}.copy-button svg{width:20px}.copy-button.clicked{opacity:1;color:var(--success);& svg[aria-live=polite]{display:block}}.copy-button.clicked svg{display:none;color:currentColor}#settings-modal-content{margin-top:10px}#settings-modal-content .hidden{display:none}#settings-modal-content .input{box-sizing:border-box;width:80%;padding:8px;font-size:var(--text-sm);background-color:var(--settingsInputBackground);color:var(--settingsInput);border:1px solid var(--settingsInputBorder);border-radius:var(--borderRadius-base);transition:var(--transition-all)}#settings-modal-content .input:focus{border-color:var(--main)}#settings-modal-content .input::placeholder{color:var(--gray400)}#settings-modal-content .switch-button-container{display:flex;align-items:center;justify-content:space-between;border-top:1px solid var(--settingsSectionBorder);padding:10px 0}#settings-modal-content .switch-button-container:first-of-type{border-top-style:none;padding-top:0}#settings-modal-content .switch-button-container>div>span{font-size:var(--text-md)}#settings-modal-content .switch-button-container>div>p{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:var(--text-sm);line-height:1.4;margin:0;padding-bottom:6px;padding-right:10px}#settings-modal-content .switch-button{position:relative;display:inline-block;flex-shrink:0;width:40px;height:20px;user-select:none;transition:var(--transition-all)}#settings-modal-content .switch-button__checkbox{appearance:none;position:absolute;display:block;width:20px;height:20px;border-radius:1000px;background-color:#91a4b7;border:3px solid #e5edf5;cursor:pointer;transition:var(--transition-all)}#settings-modal-content .switch-button__bg{display:block;width:100%;height:100%;border-radius:1000px;background-color:#e5edf5;cursor:pointer;transition:var(--transition-all)}#settings-modal-content .switch-button__checkbox:checked{background-color:#fff;border-color:var(--main);transform:translate(100%)}#settings-modal-content .switch-button__checkbox:checked+.switch-button__bg{background-color:var(--main)}#settings-modal-content .switch-button__checkbox:focus{outline:0}#settings-modal-content .switch-button__checkbox:focus+.switch-button__bg{outline:2px solid var(--main);outline-offset:2px}#settings-modal-content .switch-button__checkbox:focus:not(:focus-visible)+.switch-button__bg{outline:0}#settings-modal-content .settings-select{cursor:pointer;position:relative;border:none;background-color:transparent;color:var(--textBody)}#settings-modal-content .settings-select option{color:initial}#toast{visibility:hidden;opacity:0;position:fixed;z-index:1;left:50%;bottom:1rem;min-width:3rem;margin:0 -1.2rem;padding:.7rem 1.2rem;text-align:center;font-weight:700;border-radius:var(--borderRadius-base);border:1px solid var(--codeBorder);background-color:var(--codeBackground);color:var(--textBody);transition:opacity .4s ease-in-out,transform .3s ease-out;cursor:default}#toast.show{visibility:visible;opacity:1;transform:translateY(-.75rem)}@media (prefers-reduced-motion: reduce){#toast{transition:none}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0;user-select:none}@media print{.body-wrapper{display:block}.sidebar,.sidebar-button,.top-search{display:none}.content{padding-left:0;overflow:visible;left:0;width:100%}.summary-row{break-inside:avoid}#toast{display:none}.content-inner{padding:0}.content-inner .section-heading a.hover-link,.content-inner button.icon-action,.content-inner a.icon-action,.content-inner .bottom-actions{display:none}.footer p:first-of-type{display:none}.content-inner section.admonition{border:2px solid var(--gray400)}.content-inner section.admonition>.admonition-title{color:var(--textHeaders);border-bottom:2px solid var(--gray400)}.content-inner pre code.makeup{border-color:var(--gray400);white-space:break-spaces;break-inside:avoid}.content-inner blockquote code.inline,.content-inner code.inline{border-color:var(--gray400)}}@media print{.page-cheatmd .content-inner *{background-color:transparent!important;border-color:var(--gray400)!important}.page-cheatmd .content-inner{max-width:100%;width:100%;padding:0;font-size:.7em}.page-cheatmd .content-inner section:is(.col-2,.col-2-left,.col-3){column-gap:30px}.page-cheatmd .content-inner section.col-2{column-count:2}.page-cheatmd .content-inner section.col-2-left{display:grid}.page-cheatmd .content-inner section.col-3{column-count:3}.page-cheatmd .content-inner h1{margin-top:0;margin-bottom:.5em}.page-cheatmd .content-inner h2.section-heading{font-weight:700;margin-top:1em;column-span:all}.page-cheatmd .content-inner section.h2{break-inside:avoid}.page-cheatmd .content-inner h3{font-weight:700;color:var(--mainDark)}.page-cheatmd .content-inner h3:after{height:2px;background-color:var(--gray400)}.page-cheatmd .content-inner section.h3{min-width:300px;break-inside:avoid}.page-cheatmd .content-inner h4{padding:.5em 0;border:none;font-weight:700;color:#000}.page-cheatmd .content-inner .h2 p{padding-left:0;padding-right:0;border:none!important}.page-cheatmd .content-inner code{line-height:1.5em}.page-cheatmd .content-inner .h2 table{font-variant-numeric:tabular-nums;break-inside:avoid}.page-cheatmd .content-inner .h2 :is(th,td){vertical-align:top;padding-left:0;padding-right:0}.page-cheatmd .content-inner .h2 thead{border-style:solid none;border-width:1px}.page-cheatmd .content-inner .h2 tr{border-bottom:none}.page-cheatmd .content-inner .h2 th{font-weight:700}.page-cheatmd .content-inner .h2 li{padding-left:0;padding-right:0;vertical-align:middle;border-bottom:none}.page-cheatmd .content-inner pre:hover button.copy-button,.page-cheatmd .content-inner div.tooltip{display:none}.page-cheatmd .content-inner footer p:not(.built-using){display:none}}code.makeup .unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.makeup .hll{background-color:#ffc}.makeup .bp{color:#3465a4}.makeup .c,.makeup .c1,.makeup .ch,.makeup .cm,.makeup .cp,.makeup .cpf,.makeup .cs{color:#4d4d4d}.makeup .dl{color:#408200}.makeup .err{color:#a40000;border:#ef2929}.makeup .fm,.makeup .g{color:#4d4d4c}.makeup .gd{color:#a40000}.makeup .ge{color:#4d4d4c;font-style:italic}.makeup .gh{color:navy;font-weight:700}.makeup .gi{color:#00a000}.makeup .go{color:#4d4d4c;font-style:italic}.makeup .gp{color:#4d4d4d}.makeup .gr{color:#ef2929}.makeup .gs{color:#4d4d4c;font-weight:700}.makeup .gt{color:#a40000;font-weight:700}.makeup .gu{color:purple;font-weight:700}.makeup .il{color:#0000cf;font-weight:700}.makeup .k,.makeup .kc,.makeup .kd,.makeup .kn,.makeup .kp,.makeup .kr,.makeup .kt{color:#204a87}.makeup .l{color:#4d4d4c}.makeup .ld{color:#c00}.makeup .m,.makeup .mb,.makeup .mf,.makeup .mh,.makeup .mi,.makeup .mo{color:#2937ab}.makeup .n{color:#4d4d4c}.makeup .na{color:#8a7000}.makeup .nb{color:#204a87}.makeup .nc{color:#0000cf}.makeup .nd{color:#5c35cc;font-weight:700}.makeup .ne{color:#c00;font-weight:700}.makeup .nf{color:#b65800}.makeup .ni{color:#bc5400}.makeup .nl{color:#b65800}.makeup .nn{color:#4d4d4c}.makeup .no{color:#a06600}.makeup .nt{color:#204a87;font-weight:700}.makeup .nv,.makeup .nx{color:#4d4d4c}.makeup .o{color:#bc5400}.makeup .ow{color:#204a87}.makeup .p,.makeup .py{color:#4d4d4c}.makeup .s,.makeup .s1,.makeup .s2,.makeup .sa,.makeup .sb,.makeup .sc{color:#408200}.makeup .sd{color:#8f5902;font-style:italic}.makeup .se{color:#204a87}.makeup .sh{color:#408200}.makeup .si{color:#204a87}.makeup .sr{color:#c00}.makeup .ss{color:#a06600}.makeup .sx{color:#408200}.makeup .vc,.makeup .vg,.makeup .vi,.makeup .vm,.makeup .x{color:#4d4d4c}.dark .makeup{color:#dce1e6}.dark .makeup .hll{background-color:#49483e}.dark .makeup .bp{color:#dce1e6}.dark .makeup .c,.dark .makeup .c1,.dark .makeup .ch,.dark .makeup .cm,.dark .makeup .cp,.dark .makeup .cpf,.dark .makeup .cs{color:#969386}.dark .makeup .dl{color:#e6db74}.dark .makeup .err{color:#960050;background-color:#1e0010}.dark .makeup .fm{color:#a6e22e}.dark .makeup .gd{color:#ff5385}.dark .makeup .ge{font-style:italic}.dark .makeup .gi{color:#a6e22e}.dark .makeup .gp{color:#969386}.dark .makeup .gs{font-weight:700}.dark .makeup .gu{color:#969386}.dark .makeup .gt{color:#ff5385;font-weight:700}.dark .makeup .il{color:#ae81ff}.dark .makeup .k,.dark .makeup .kc,.dark .makeup .kd{color:#66d9ef}.dark .makeup .kn{color:#ff5385}.dark .makeup .kp,.dark .makeup .kr,.dark .makeup .kt{color:#66d9ef}.dark .makeup .l,.dark .makeup .ld,.dark .makeup .m,.dark .makeup .mb,.dark .makeup .mf,.dark .makeup .mh,.dark .makeup .mi,.dark .makeup .mo{color:#ae81ff}.dark .makeup .n{color:#dce1e6}.dark .makeup .na{color:#a6e22e}.dark .makeup .nb{color:#dce1e6}.dark .makeup .nc,.dark .makeup .nd,.dark .makeup .ne,.dark .makeup .nf{color:#a6e22e}.dark .makeup .ni,.dark .makeup .nl,.dark .makeup .nn{color:#dce1e6}.dark .makeup .no{color:#66d9ef}.dark .makeup .nt{color:#ff5385}.dark .makeup .nv{color:#dce1e6}.dark .makeup .nx{color:#a6e22e}.dark .makeup .o,.dark .makeup .ow{color:#ff5385}.dark .makeup .p,.dark .makeup .py{color:#dce1e6}.dark .makeup .s,.dark .makeup .s1,.dark .makeup .s2,.dark .makeup .sa,.dark .makeup .sb,.dark .makeup .sc,.dark .makeup .sd{color:#e6db74}.dark .makeup .se{color:#ae81ff}.dark .makeup .sh,.dark .makeup .si,.dark .makeup .sr,.dark .makeup .ss,.dark .makeup .sx{color:#e6db74}.dark .makeup .vc,.dark .makeup .vg,.dark .makeup .vi,.dark .makeup .vm{color:#dce1e6}.tabset{--borderWidth: 1px;--tabsetPadding: var(--baseLineHeight);margin:var(--baseLineHeight) 0;border:var(--borderWidth) solid var(--tabBorder);padding:0 var(--tabsetPadding);border-radius:var(--borderRadius-lg)}.tabset-tablist{display:flex;overflow:auto;scrollbar-width:thin;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:var(--tabBorderTop)}.tabset-tab{padding:1.1rem var(--tabsetPadding);font-family:var(--sansFontFamily);color:var(--textColor);margin-right:calc(-1 * var(--borderWidth));background-color:transparent;border:0;box-shadow:none;cursor:pointer;border-bottom-width:2px;border-bottom-style:solid;border-bottom-color:transparent;transition:var(--transition-all)}:hover.tabset-tab{border-bottom-color:var(--tabBorderTop);color:var(--textHeaders)}.tabset-tab[aria-selected=true]{border-bottom-color:var(--mainLight);color:var(--textHeaders)}.tabset-tab[aria-selected=true]:focus-visible{background-color:var(--mainLight);border-color:var(--mainLight);color:var(--white)}@media screen and (max-width: 768px){.tabset{--tabsetPadding: calc(var(--baseLineHeight) / 2)}.tabset-panel{padding-top:calc(var(--tabsetPadding) / 2);padding-bottom:calc(var(--tabsetPadding) / 2)}.tabset-panel pre,.tabset-panel blockquote,.tabset-panel section.admonition{margin-left:calc(-1 * var(--tabsetPadding))!important;margin-right:calc(-1 * var(--tabsetPadding))!important}.tabset-panel>pre code{border-left-width:0;border-right-width:0}}@media screen and (max-width: 768px){.tabset-panel>:is(:first-child){&:is(table){margin:.5em 0}}}@media screen and (min-width: 769px){.tabset-panel>:is(:first-child){&:is(blockquote,.admonition){margin-top:1.5em}&:is(p:has(img)){margin-top:1.25em}&:is(table){margin-top:.75em}}.tabset-panel>:is(:last-child){&:is(blockquote,.admonition){margin-bottom:1.5em}&:is(p:not(:has(img)),ul,ol){margin-bottom:1.25em}&:is(table){margin-bottom:.75em}}}body.preview{--sidebarWidth: 0px;overflow:hidden}body.preview .content{height:auto}body.preview .content-inner{padding:0}body.preview .sidebar,body.preview #sidebar-menu,body.preview .hover-link,body.preview .detail-link{display:none}body.preview :is(h1,h2,h3):first-of-type{margin-top:0}body:not(.dark) .content-inner img[src*="#gh-dark-mode-only"],body.dark .content-inner img[src*="#gh-light-mode-only"]{display:none} +/*! Bundled license information: + +modern-normalize/modern-normalize.css: + (*! modern-normalize v3.0.1 | MIT License | https://github.com/sindresorhus/modern-normalize *) +*/ diff --git a/site/dist/lato-latin-400-normal-W7754I4D.woff2 b/site/dist/lato-latin-400-normal-W7754I4D.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..ff60934dd0ea9cdd93f961d2dfd1e158357f2a77 GIT binary patch literal 23580 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 QOFh<%JiLFgmWQ+r07g396aWAK literal 0 HcmV?d00001 diff --git a/site/dist/lato-latin-700-normal-2XVSBPG4.woff2 b/site/dist/lato-latin-700-normal-2XVSBPG4.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..11de83feaf0fb872c91fce89534fd4e2d8bbda28 GIT binary patch literal 23040 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 literal 0 HcmV?d00001 diff --git a/site/dist/lato-latin-ext-400-normal-N27NCBWW.woff2 b/site/dist/lato-latin-ext-400-normal-N27NCBWW.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..edb9fa6f492362a9ab1f1d674b8f6e6f4e2085d0 GIT binary patch literal 5472 zcmV-m6`$&NPew8T0RR9102N>W5C8xG04}Tm02KuQ0RR9100000000000000000000 z0000Rfi4^<24Dbz1PCq(jb#xG3cgUfZ3|cc0X7081A!(4AO(dO2Z9g`OB+}#MMm^E zK!RTz!TEr^>}cb40HcIluGU7qGI6xzh9=k z_rn5CPSloJRfl!z>ncp;{`&^<-kU$eN&bW;S;7h6(kuXyDzK{qcEFB|trsg~Uo*8g zBs}LZW$`!r6+M}ELTN$?km|VCC-!&pmjn<1>{24LJy|3H>@zpl0fGPkrVzcx0L%_u z6U{F9AtkLexl<+EdUdV5MV2rgCl(}^Guvd(ffHxu#<_u<=cv`7#H1K8OHdp~<(`$$ ztN^)_3TB$m0A?|1LbeN?0=UQ`$2ad&ZNL(iwR&{Awz{=R>;rf95CWFU+5r@1EcIHsr`UMOUO&tRcEv z%h!JgV1B@I;QA-%%)|2fmtS|c;1ISf(%#^v-KBsoS1rER5b+nW{oQ)=uDnCMp=mwq zuyZtt?f-4 zm1ACUnx>2LU~e<))=1)E?EU2FmBDH8^gDE9O1nk2E9WBBRauk_6k-UO13_kC&P$LPhc`@(IC*+b8*qjy*NH|52YxT`t z-FgL8qNFLAA-3f<3*e@46y>3>k@nWfeaD+HRSfKQ`p~LQRp0#h`d4V8hBH)E+Xf@`P#(i52aOcQ>fCNI@4h)$-;IYIKRd zrjZbw+ym)Ol&Rak1(})5KgoU5^N!;bYIc;Sx?5!sHaWhrszO5CTro}nA zb_ZY+NE}}Db2F$%cuO4jrvh)oiFZp2PPHvK)3)S!iMQdxyS;}?Z5yt%Z9osv7!X*0BhrWUCF6q+HJzlg8mcP0vB^F*^l)|-F+DvE zOkKKn?i^DB%k~|;`0(OU$T$Ok>r_A7$?h;tB2EvC0K@&K;LaxoatBFF#z4rN8&)k`Lk~O7mz_bl9dlhkgSXU3LW7i?b8tH&Ld)bDadqEwB zVC4`O8uv6UHbhjGzr8P*_rda^W{&(&AesFKX|sSW4M^7jt8!$5wfksb_4XkI!2qvz zGN8!li;*B~%NDrv%$9-duH)+}78xw(jS$aat}P02b-qjp<~1-1jJ!M*XJTpp{M z*XZ>91`m&>aOKK#u_b$G%|t+uaX;EdfQXoUOE(PX?>>ukbZwUVZ4>%a)y+nwZSDrEO~JT;U)i zWOBX(T21;wQ=Cj?;{0tYWeFG=5R7;l|1xB4_qch|g0$|33Df+lvr|60CG*JYgay%t zH-u>bH>DX7kdg#4dgfaqm_`ojz1Jx0rC zXY;$x1Nv~shhi>fj^ir*${-ApuMbOgFM=t%-R9fgH?&4DSVp0bx}VLxgxKA(e0hR> z7AYXE%q2C>t1v3kA^T3@?`{#K3Ioy{yy;H)|9^Xhrt+e_8(St2)^V#)%fL55jE4I* zC~AGbff4kY{#*A0kgf-G4XCsllhPqC(!GqleBD2d6TAPdnz*FGA39WlKY!V#>cGB_ zD!G_1ue2xQuV9KaI~7HszmTw?_{s}HS}YY zHwpc75Tr|u{`fw0Dw63$`~UL)PTEaT*G{kFlgO77y_C*LLXAs2&p9VBhMT2~GV0MxNbwok))=skJ=n*WRancKrhY-Z}Jl-RlBDrdMbEAZk{62;IYKZ5U!AN zmncNswe_{#!s_k8jrQ|V()bs%9@Zwq1ds7PeBg^3xqk> z)9Vz6lG?sXyu6^1f3dxDB2!;=IPnLQ<)+`OJhtF#g{g-Ms>O>UBwF9KvgJpX>nj%3 zWUtDI7JTz-&}1EF5v5fbj4=NchG(~v=hZa#5_>hL#50ZOCyPxEZdJ+F2A5O~B_8)q zSWrTtV8$G~*sx4?Y?q7AjWmx^d$m)kS6ZxJp^zI`Rg|+lP^R6--*zKhJV1Ri;`+?H z>)&+zm5Uy)o!9)-<}MwWgI*8Qt2X~UGft>XFloJ#W+$8}whxtSv*Ni~+T*Oh^~(#E zr5Y+b);8Dao!8Z$o)+X_I1vb(^H$M+})~w`$upLODm^^%kXUTKktc=ko2}K)Nil zK;yqwdY>JbNlA2h_h!;yKIB*(9F*YWwe#4xX-=Rd|9yHvy7c?TU;6Lx|9X61(dgzh zP0l@ee!s(o#bIU8aLU5fNjHsEf|DI9#zb{RJ7emb`296LcC15?B5nvkg@b?I0N^0D^g}ls@?_4HKFZD8AWN&s~eAVbMqCNY%=5T<| znbPI#H3y~lt}JJ5z098wm648p-WLDwk<;TDl@6WT6Bh42V3I#$-uvOyOlfqCe-7(w z-y-V-`NLfVVJbCkn%0M2|K`GTwZjRgfE?D}e#JHk^n>xnzd^b%T!Ccqg8qWU%7pc_ zq!mcpYwO-3J35ywa-L+fuaaY&jZeAyv6^(rvbWZ3b6W4~l3|l=n~kW^FRkH`GRBuo zs{^b=fW=NRs}4YVTUlgyE40k^z-m(??#5CEXxD(5bCC)kuMdxfRS$+by zGLC&?2a`v-%3>Y`Crp+vbd<@uO6IwLWZ-=QC>-h^0M(W_;9q7^QGcm*4U_>rt6A$c z;4Aek^O44hyL?J5i3fU#S<%$j>HWdKEixbL9hvv|PVytMtAB;?!|UGz-gW&`vd#aM ze*KFtP6K=u=?VDJP4M4jJw7@F#GmJ1$RIvW=gEA0D=V88s&>YZ zcJZIW&h_(W->>K6Joa_2%QOx=MaH8mC$An?G;%=#kf9lFGS@v6rnm&mF|kjOY9z5w zYZ-RQxi_cQ0=tybFN?PG>hYRJE)YUKGt3tZ2%8f!e)37&b=&BkS>WZv5VPc4yB}P6{M*aWy-@F zg2C;)n1$Hi!q!5_J8NF=DpC@w1D%JKWl}Y9j4f4RyH>wDr*lH0g$#Ogms#HyMpTk- z(`;y`jc`t}UxOL2>Pqr;FMVh22?`ETm|#WV7LM&BaU-M=O7A3g5(4kZGEXAcrb<|D zuO;+Zpfpps%|I^v9v3FhUk3tB*wjZg68$ z7KW|3xIo9K!!~9CWVyqxE5UG{!Xgd>6&~l#)X88tV&A*@f+<;z)HtPVhsFvRVc=Xn zAHxVn-_M>kF<7RZb-*VjiY@HXTrcW{5&?x=xXkbLz0bsbqR8UVvB>O7Uwr2EJ|v5@ zY`P!@mT>6~3gLmjqyk4ZJ5&Qvt~s{u4>a{q34fOym-O|-C`HS!pc z*7vNL;^;7q9osSuO_umU%^c{U148<-gHAzBAz?ErZuQaIDW%>#`%{H^X$B!C#&0Vv z`Ix3hLfIZoSTV{ypdw0XTroQWVIopcZ|@!+g|(LBFqWHC(<4AkXd|3UDW256hvUY* zCW=!o!B9D@CPL>+Th^U*R&f}zhv&FQn1=GiFP|7|^*__j=)#afTrgI=j z2pF5qrNb{p-@tNQ7#RYputP-#<`EXP!?kD3>-pb^=NNcaA?1?#Wvb6DY%P+yvo3_T zI#r6hu7J{3Q5P$8p0jM$Hh$sDztZ`i9#V+SqJ8a`B04TXuSn#QGK3=@G0;mW#R63^ zHfHNmRIgl6S~Sf%XwU`_aWYzKu%RN2v5|&)4#yraC9PhE$^(0r6Un1ruzhY}gazl) zom93|8O2^uIjrVpw)Ayp;B6RcF{{V0!%yXH(R*%=&wT(dtYcrwe`)mNO_isiZ|bgn z=ovlJ?~>%NlpnW0K#mkS-J=n?h1l=;qu9*)Nwp{F}RGnQWP!9y4yW7v`wf6;u9!Ao-x*YOVvW9h@y3 z-%qgaq&Swf8wlGgD~@JYS>C~Fq#bp|>TcxPhOWqD4zHudv_1I^q^wzzmEB{jj4GIv zk&x}qF}%p$HY{&lMr3l?9!Nnf(hA@X?MaCW2I@ORkys5$=VF=XIkZ=2k;2kFlmMwp zV;Zb@$iu?G=u9m#tSTOD2J8I*<|cP(AZ1Y+nQ=M>>ImYI1H12zA<9~jhB>VK5avj6 za*(tvd7n-*$I>-fWV^5p#-5GupcxugbMD-P!+nP9LrFg+sMeZ@ZT>KA=-z!T6Ru3) zun%Jw7`PxEzS$9k?K{j$ISe56p{-2Xe*jXHm3rWmIeT8->(C6OBbXx#!%Er6(w-QU zR8mKhlf-x!udWrmBkXq9Hl4z@ndWr%CVB#D|a<_2YOV+)YDB=c?OZ4*%~zKT(Wg{!>}ymw+FC ztn^X7{NGi}P2+!aJze~Ph5;Zb-~GP~%}5QBFcrkniw@&}Gu{z>1k$^BSDN$H?#5H` zPc?q;ZQjePLe57gEzkMqd6|{*qm)DE|5dEV)Oa_SGxxH5POUta5`kr?l1K$yeZnQ# ziA{KYmt$8^)ye>v`7sDu>zICW==wXS=J6Y( zj^&e5Yx_wvtoo#Ti(^lQoAx}Jyn%>kTo2>J(gA=9&C{a|xB_GKG@4YxyctRepyxF^ zuSa<~?UmV*iHN9-(!pOI9nM>*T;;e7luf$VQm+n2umHh=gyG@Hr=!m6?)7HR0rrNk*{)`7xR($W$UpxSuxY=cAwl~OA&p9U8Pk5twsM37*? zjZ0G|(32h9$a2oAa(L13Mkos6k7aSFIYZ~r9Fo%xmD3tBp-rV;A@y9zR>eGyWLAkl zY!;PTI`4HMn&%?G4B;^z9on*m0F{zsfJ#d&%@=TFbM7+HcO>xZw^QjfXy)k+O_z3` zSYH5Y7`HE2gcz}s<&r6}R^|%+2j-!q%pZNIqN=8jKl|jY5cM_CkiYt(mv>%TDx$_B zixOWoE@CaL|4-wBYHO9OCuzDKt+G^_mS&w*U8RXNy;i6i+QWs~`sPUQTEc6n=frC( zb?-)zJ|L@vHSEIqMWNI>FF}i4KKs)ZRPO@`$ym5NvbmKwO#6SK>*If>d>F0v(3+*f WhF)K4IGNT+hd8;|K8&%*Sz!P*WW1>W literal 0 HcmV?d00001 diff --git a/site/dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 b/site/dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..2c8aaa866eee8bee09ee05a9809c2fda7cd87bd1 GIT binary patch literal 5368 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 al http://Host:PortPrefix/DbName If ssl is set https is used. See server_connections for options. Params is a list of optionnal query argument you want to pass to the db. Useful for bigcouch for example. Options::optionList(), Params::list()) -> {ok, db()|{error, Error}}","ref":"couchbeam.html#create_db/4"},{"type":"type","title":"couchbeam.db/0","doc":"","ref":"couchbeam.html#t:db/0"},{"type":"function","title":"couchbeam.db_exists/2","doc":"test if db with dbname exists on the CouchDB node","ref":"couchbeam.html#db_exists/2"},{"type":"function","title":"couchbeam.db_info/1","doc":"get database info","ref":"couchbeam.html#db_info/1"},{"type":"function","title":"couchbeam.delete_attachment/3","doc":"Equivalent to delete_attachment(Db, Doc, Name, []) . delete a document attachment","ref":"couchbeam.html#delete_attachment/3"},{"type":"function","title":"couchbeam.delete_attachment/4","doc":"delete a document attachment","ref":"couchbeam.html#delete_attachment/4"},{"type":"function","title":"couchbeam.delete_db/1","doc":"Equivalent to delete_db(Server, DbName) . delete database","ref":"couchbeam.html#delete_db/1"},{"type":"function","title":"couchbeam.delete_db/2","doc":"delete database","ref":"couchbeam.html#delete_db/2"},{"type":"function","title":"couchbeam.delete_doc/2","doc":"Equivalent to delete_doc(Db, Doc, []) . delete a document","ref":"couchbeam.html#delete_doc/2"},{"type":"function","title":"couchbeam.delete_doc/3","doc":"delete a document if you want to make sure the doc it emptied on delete, use the option {empty_on_delete, true} or pass a doc with just _id and _rev members.","ref":"couchbeam.html#delete_doc/3"},{"type":"function","title":"couchbeam.delete_docs/2","doc":"Equivalent to delete_docs(Db, Docs, []) . delete a list of documents","ref":"couchbeam.html#delete_docs/2"},{"type":"function","title":"couchbeam.delete_docs/3","doc":"delete a list of documents if you want to make sure the doc it emptied on delete, use the option {empty_on_delete, true} or pass a doc with just _id and _rev members.","ref":"couchbeam.html#delete_docs/3"},{"type":"function","title":"couchbeam.design_info/2","doc":"","ref":"couchbeam.html#design_info/2"},{"type":"type","title":"couchbeam.doc/0","doc":"","ref":"couchbeam.html#t:doc/0"},{"type":"function","title":"couchbeam.doc_exists/2","doc":"test if doc with uuid exists in the given db","ref":"couchbeam.html#doc_exists/2"},{"type":"opaque","title":"couchbeam.doc_stream/0","doc":"","ref":"couchbeam.html#t:doc_stream/0"},{"type":"type","title":"couchbeam.ejson_object/0","doc":"","ref":"couchbeam.html#t:ejson_object/0"},{"type":"function","title":"couchbeam.end_doc_stream/1","doc":"stop to receive the multipart response of the doc api and close the connection.","ref":"couchbeam.html#end_doc_stream/1"},{"type":"function","title":"couchbeam.ensure_full_commit/1","doc":"Equivalent to ensure_full_commit(Db, []) . commit all docs in memory","ref":"couchbeam.html#ensure_full_commit/1"},{"type":"function","title":"couchbeam.ensure_full_commit/2","doc":"commit all docs in memory","ref":"couchbeam.html#ensure_full_commit/2"},{"type":"function","title":"couchbeam.fetch_attachment/3","doc":"Equivalent to fetch_attachment(Db, DocId, Name, []) . fetch a document attachment","ref":"couchbeam.html#fetch_attachment/3"},{"type":"function","title":"couchbeam.fetch_attachment/4","doc":"fetch a document attachment Options are stream : to start streaming an attachment. the function return {ok, Ref} where is a ref to the attachment Other options that can be sent using the REST API","ref":"couchbeam.html#fetch_attachment/4"},{"type":"function","title":"couchbeam.find/3","doc":"","ref":"couchbeam.html#find/3"},{"type":"function","title":"couchbeam.get_missing_revs/2","doc":"get missing revisions","ref":"couchbeam.html#get_missing_revs/2"},{"type":"function","title":"couchbeam.get_uuid/1","doc":"Get one uuid from the server","ref":"couchbeam.html#get_uuid/1"},{"type":"function","title":"couchbeam.get_uuids/2","doc":"Get a list of uuids from the server","ref":"couchbeam.html#get_uuids/2"},{"type":"function","title":"couchbeam.lookup_doc_rev/2","doc":"get the last revision of the document","ref":"couchbeam.html#lookup_doc_rev/2"},{"type":"function","title":"couchbeam.lookup_doc_rev/3","doc":"","ref":"couchbeam.html#lookup_doc_rev/3"},{"type":"type","title":"couchbeam.mp_attachment/0","doc":"","ref":"couchbeam.html#t:mp_attachment/0"},{"type":"type","title":"couchbeam.mp_attachments/0","doc":"","ref":"couchbeam.html#t:mp_attachments/0"},{"type":"function","title":"couchbeam.open_db/2","doc":"Equivalent to open_db(Server, DbName, []) . Create a client for connection to a database","ref":"couchbeam.html#open_db/2"},{"type":"function","title":"couchbeam.open_db/3","doc":"Create a client for connection to a database -> {ok, db()}","ref":"couchbeam.html#open_db/3"},{"type":"function","title":"couchbeam.open_doc/2","doc":"Equivalent to open_doc(Db, DocId, []) . open a document","ref":"couchbeam.html#open_doc/2"},{"type":"function","title":"couchbeam.open_doc/3","doc":"open a document Params is a list of query argument. Have a look in CouchDb API -> {ok, Doc}|{error, Error}","ref":"couchbeam.html#open_doc/3"},{"type":"function","title":"couchbeam.open_or_create_db/2","doc":"Equivalent to open_or_create_db(Server, DbName, [], []) . Create a client for connecting to a database and create the database if needed.","ref":"couchbeam.html#open_or_create_db/2"},{"type":"function","title":"couchbeam.open_or_create_db/3","doc":"Equivalent to open_or_create_db(Server, DbName, Options, []) . Create a client for connecting to a database and create the database if needed.","ref":"couchbeam.html#open_or_create_db/3"},{"type":"function","title":"couchbeam.open_or_create_db/4","doc":"Create a client for connecting to a database and create the database if needed.","ref":"couchbeam.html#open_or_create_db/4"},{"type":"function","title":"couchbeam.put_attachment/4","doc":"Equivalent to put_attachment(Db, DocId, Name, Body, []) . put an attachment","ref":"couchbeam.html#put_attachment/4"},{"type":"function","title":"couchbeam.put_attachment/5","doc":"put an attachment Body::body(), Option::optionList()) -> {ok, iolist()} optionList() = [option()] option() = {rev, string()} | {content_type, string()} | {content_length, string()} body() = [] | string() | binary() | fun_arity_0() | {fun_arity_1(), initial_state(), stream} initial_state() = term()","ref":"couchbeam.html#put_attachment/5"},{"type":"function","title":"couchbeam.replicate/2","doc":"Handle replication. Pass a map containing all information. It allows passing authentication info, etc. RepObj = #{\n <<"source">> => <<"sourcedb">>,\n <<"target">> => <<"targetdb">>,\n <<"create_target">> => true\n }.\n replicate(Server, RepObj). -> {ok, Result}|{error, Error}","ref":"couchbeam.html#replicate/2"},{"type":"function","title":"couchbeam.replicate/3","doc":"Handle replication. -> {ok, Result}|{error, Error}","ref":"couchbeam.html#replicate/3"},{"type":"function","title":"couchbeam.replicate/4","doc":"handle Replication. Allows to pass options with source and target. Source and target can be either simple URI strings or complex document structures with authentication. Options is a Json object. ex: %% Simple URI replication\n Options = [{<<"create_target">>, true}]},\n couchbeam:replicate(S, "testdb", "testdb2", Options).\n \n %% Complex replication with authentication\n Source = "http://user:pass@remote.com:5984/db",\n Target = #{\n <<"url">> => <<"http://localhost:5984/target_db">>,\n <<"auth">> => #{\n <<"basic">> => #{<<"username">> => <<"user">>,\n <<"password">> => <<"pass">>}\n }\n },\n couchbeam:replicate(S, Source, Target, [{<<"continuous">>, true}]).","ref":"couchbeam.html#replicate/4"},{"type":"function","title":"couchbeam.save_doc/2","doc":"Equivalent to save_doc(Db, Doc, []) . save a document","ref":"couchbeam.html#save_doc/2"},{"type":"function","title":"couchbeam.save_doc/3","doc":"save a *document A document is a Json object like this one: #{\n <<"_id">> => <<"myid">>,\n <<"title">> => <<"test">>\n } Options are arguments passed to the request. This function return a new document with last revision and a docid. If _id isn't specified in document it will be created. Id is created by extracting an uuid from the couchdb node.","ref":"couchbeam.html#save_doc/3"},{"type":"function","title":"couchbeam.save_doc/4","doc":"save a *document with all its attacjments A document is a Json object like this one: #{\n <<"_id">> => <<"myid">>,\n <<"title">> => <<"test">>\n } Options are arguments passed to the request. This function return a new document with last revision and a docid. If _id isn't specified in document it will be created. Id is created by extracting an uuid from the couchdb node. If the attachments is not empty, the doc will be sent as multipart. Attachments are passed as a list of the following tuples: - {Name :: binary(), Bin :: binary()} - {Name :: binary(), Bin :: binary(), Encoding :: binary()} - { Name :: binary(), Bin :: binary(), Type :: binary(), Encoding :: binary()} - { Name :: binary(), {file, Path :: string()}} - { Name :: binary(), {file, Path :: string()}, Encoding :: binary()} - { Name :: binary(), Fun :: fun(), Length :: integer()} - { Name :: binary(), Fun :: fun(), Length :: integer(), Encoding :: binary()} - {Name :: binary(), Fun :: fun(), Length :: integer(), Type :: binary(), Encoding :: binary()} - { Name :: binary(), {Fun :: fun(), Acc :: any()}, Length :: integer()} - { Name :: binary(), {Fun :: fun(), Acc :: any()}, Length :: integer(), Encoding :: binary()} - { Name :: binary(), {Fun :: fun(), Acc :: any()}, Length :: integer(), Type :: binary(), Encoding :: binary()}. where Type` is the content-type of the attachments (detected in other case) and `Encoding` the encoding of the attachments: `<<\"identity\">> if normal or <<\"gzip\">> if the attachments is gzipped.","ref":"couchbeam.html#save_doc/4"},{"type":"function","title":"couchbeam.save_docs/2","doc":"Equivalent to save_docs(Db, Docs, []) . save a list of documents","ref":"couchbeam.html#save_docs/2"},{"type":"function","title":"couchbeam.save_docs/3","doc":"save a list of documents","ref":"couchbeam.html#save_docs/3"},{"type":"function","title":"couchbeam.send_attachment/2","doc":"send an attachment chunk Msg could be Data, eof to stop sending.","ref":"couchbeam.html#send_attachment/2"},{"type":"type","title":"couchbeam.server/0","doc":"","ref":"couchbeam.html#t:server/0"},{"type":"function","title":"couchbeam.server_connection/0","doc":"Equivalent to server_connection(URL, Options) . Create a server for connectiong to a CouchDB node","ref":"couchbeam.html#server_connection/0"},{"type":"function","title":"couchbeam.server_connection/1","doc":"","ref":"couchbeam.html#server_connection/1"},{"type":"function","title":"couchbeam.server_connection/2","doc":"Equivalent to server_connection(Host, Port, \"\", []) . Create a server for connectiong to a CouchDB node","ref":"couchbeam.html#server_connection/2"},{"type":"function","title":"couchbeam.server_connection/4","doc":"Create a server for connectiong to a CouchDB node Connections are made to: http://Host:PortPrefix If ssl is set https is used. For a description of SSL Options, look in the ssl manpage.","ref":"couchbeam.html#server_connection/4"},{"type":"function","title":"couchbeam.server_info/1","doc":"Get Information from the server","ref":"couchbeam.html#server_info/1"},{"type":"function","title":"couchbeam.stream_attachment/1","doc":"fetch an attachment chunk. Use this function when you pass the stream option to the couchbeam:fetch_attachment/4 function. This function return the following response: done You got all the attachment {ok, binary()} Part of the attachment {error, term()} n error occurred","ref":"couchbeam.html#stream_attachment/1"},{"type":"function","title":"couchbeam.stream_doc/1","doc":"stream the multipart response of the doc API. Use this function when you get {ok, {multipart, State}} from the function couchbeam:open_doc/3 .","ref":"couchbeam.html#stream_doc/1"},{"type":"function","title":"couchbeam.view_cleanup/1","doc":"","ref":"couchbeam.html#view_cleanup/1"},{"type":"module","title":"couchbeam_app","doc":"","ref":"couchbeam_app.html"},{"type":"function","title":"couchbeam_app.start/2","doc":"","ref":"couchbeam_app.html#start/2"},{"type":"function","title":"couchbeam_app.stop/1","doc":"","ref":"couchbeam_app.html#stop/1"},{"type":"module","title":"couchbeam_attachments","doc":"This module contains utilities to manage attachments","ref":"couchbeam_attachments.html"},{"type":"function","title":"couchbeam_attachments.add_inline/3","doc":"add attachment to a doc and encode it. Give possibility to send attachments inline.","ref":"couchbeam_attachments.html#add_inline/3"},{"type":"function","title":"couchbeam_attachments.add_inline/4","doc":"add attachment to a doc and encode it with ContentType fixed.","ref":"couchbeam_attachments.html#add_inline/4"},{"type":"function","title":"couchbeam_attachments.add_stub/3","doc":"","ref":"couchbeam_attachments.html#add_stub/3"},{"type":"function","title":"couchbeam_attachments.delete_inline/2","doc":"delete an attachment record in doc. This is different from delete_attachment change is only applied in Doc object. Save_doc should be save to save changes.","ref":"couchbeam_attachments.html#delete_inline/2"},{"type":"type","title":"couchbeam_attachments.doc/0","doc":"","ref":"couchbeam_attachments.html#t:doc/0"},{"type":"type","title":"couchbeam_attachments.ejson_object/0","doc":"","ref":"couchbeam_attachments.html#t:ejson_object/0"},{"type":"module","title":"couchbeam_changes","doc":"","ref":"couchbeam_changes.html"},{"type":"function","title":"couchbeam_changes.cancel_stream/1","doc":"","ref":"couchbeam_changes.html#cancel_stream/1"},{"type":"type","title":"couchbeam_changes.changes_option/0","doc":"","ref":"couchbeam_changes.html#t:changes_option/0"},{"type":"type","title":"couchbeam_changes.changes_options/0","doc":"","ref":"couchbeam_changes.html#t:changes_options/0"},{"type":"type","title":"couchbeam_changes.db/0","doc":"","ref":"couchbeam_changes.html#t:db/0"},{"type":"function","title":"couchbeam_changes.follow/1","doc":"","ref":"couchbeam_changes.html#follow/1"},{"type":"function","title":"couchbeam_changes.follow/2","doc":"Stream changes to a pid Db : a db record Client : pid or callback where to send changes events where events are The pid receive these events: {change, StartRef, {done, Lastseq::integer()} Connection terminated or you got all changes {change, StartRef, Row :: ejson_object()} Line of change {error, LastSeq::integer(), Msg::term()} Got an error, connection is closed when an error happend. LastSeq is the last sequence of changes. While the callbac could be like: fun({done, LastSeq}) ->\n ok;\n fun({done, LastSeq}) ->\n ok;\n fun({done, LastSeq}) ->\n ok. >Options :: changes_stream_options() [continuous\n | longpoll\n | normal\n | include_docs\n | {since, integer() | now}\n | {timeout, integer()}\n | heartbeat | {heartbeat, integer()}\n | {filter, string()} | {filter, string(), list({string(), string() | integer()})}\n | {view, string()},\n | {docids, list))},\n | {stream_to, pid()},\n | {async, once | normal}] continuous | longpoll | normal : set the type of changes feed to get include_doc : if you want to include the doc in the line of change {timeout, Timeout::integer()} : timeout heartbeat | {heartbeat, Heartbeat::integer()} : set couchdb to send a heartbeat to maintain connection open {filter, FilterName} | {filter, FilterName, Args::list({key, value})} : set the filter to use with optional arguments {view, ViewName} : use a view function as filter. Note that it requires to set filter special value \"_view\" to enable this feature. > {stream_to, Pid} : the pid where the changes will be sent, by default the current pid. Used for continuous and longpoll connections Return {ok, StartRef, ChangesPid} or {error, Error}. Ref can be used to disctint all changes from this pid. ChangesPid is the pid of the changes loop process. Can be used to monitor it or kill it when needed.","ref":"couchbeam_changes.html#follow/2"},{"type":"function","title":"couchbeam_changes.follow_once/1","doc":"","ref":"couchbeam_changes.html#follow_once/1"},{"type":"function","title":"couchbeam_changes.follow_once/2","doc":"fetch all changes at once using a normal or longpoll connections. Db : a db record Options :: changes_options() [\n | longpoll\n | normal\n | include_docs\n | {since, integer() | now}\n | {timeout, integer()}\n | heartbeat | {heartbeat, integer()}\n | {filter, string()}\n | {filter, string(), list({string(), string() | integer()})}\n | {docids, list()))},\n | {stream_to, pid()}\n ] longpoll | normal : set the type of changes feed to get include_docs : if you want to include the doc in the line of change {timeout, Timeout::integer()} : timeout heartbeat | {heartbeat, Heartbeat::integer()} : set couchdb to send a heartbeat to maintain connection open {filter, FilterName} | {filter, FilterName, Args::list({key, value}) : set the filter to use with optional arguments {view, ViewName} : use a view function as filter. Note that it requires to set filter special value \"_view\" to enable this feature. Result: {ok, LastSeq::integer(), Rows::list()} or {error, LastSeq, Error} . LastSeq is the last sequence of changes.","ref":"couchbeam_changes.html#follow_once/2"},{"type":"type","title":"couchbeam_changes.server/0","doc":"","ref":"couchbeam_changes.html#t:server/0"},{"type":"function","title":"couchbeam_changes.stream_next/1","doc":"","ref":"couchbeam_changes.html#stream_next/1"},{"type":"module","title":"couchbeam_changes_stream","doc":"","ref":"couchbeam_changes_stream.html"},{"type":"function","title":"couchbeam_changes_stream.init_stream/5","doc":"","ref":"couchbeam_changes_stream.html#init_stream/5"},{"type":"function","title":"couchbeam_changes_stream.maybe_continue/1","doc":"","ref":"couchbeam_changes_stream.html#maybe_continue/1"},{"type":"function","title":"couchbeam_changes_stream.start_link/4","doc":"","ref":"couchbeam_changes_stream.html#start_link/4"},{"type":"function","title":"couchbeam_changes_stream.system_code_change/4","doc":"","ref":"couchbeam_changes_stream.html#system_code_change/4"},{"type":"function","title":"couchbeam_changes_stream.system_continue/3","doc":"","ref":"couchbeam_changes_stream.html#system_continue/3"},{"type":"function","title":"couchbeam_changes_stream.system_terminate/4","doc":"","ref":"couchbeam_changes_stream.html#system_terminate/4"},{"type":"function","title":"couchbeam_changes_stream.wait_reconnect/1","doc":"","ref":"couchbeam_changes_stream.html#wait_reconnect/1"},{"type":"module","title":"couchbeam_changes_sup","doc":"","ref":"couchbeam_changes_sup.html"},{"type":"function","title":"couchbeam_changes_sup.init/1","doc":"","ref":"couchbeam_changes_sup.html#init/1"},{"type":"function","title":"couchbeam_changes_sup.start_link/0","doc":"","ref":"couchbeam_changes_sup.html#start_link/0"},{"type":"module","title":"couchbeam_doc","doc":"","ref":"couchbeam_doc.html"},{"type":"function","title":"couchbeam_doc.delete_value/2","doc":"Deletes all entries associated with Key in json object.","ref":"couchbeam_doc.html#delete_value/2"},{"type":"type","title":"couchbeam_doc.doc/0","doc":"","ref":"couchbeam_doc.html#t:doc/0"},{"type":"type","title":"couchbeam_doc.ejson_array/0","doc":"","ref":"couchbeam_doc.html#t:ejson_array/0"},{"type":"type","title":"couchbeam_doc.ejson_number/0","doc":"","ref":"couchbeam_doc.html#t:ejson_number/0"},{"type":"type","title":"couchbeam_doc.ejson_object/0","doc":"","ref":"couchbeam_doc.html#t:ejson_object/0"},{"type":"type","title":"couchbeam_doc.ejson_string/0","doc":"","ref":"couchbeam_doc.html#t:ejson_string/0"},{"type":"type","title":"couchbeam_doc.ejson_term/0","doc":"","ref":"couchbeam_doc.html#t:ejson_term/0"},{"type":"function","title":"couchbeam_doc.extend/2","doc":"extend a jsonobject by a property, list of property or another jsonobject","ref":"couchbeam_doc.html#extend/2"},{"type":"function","title":"couchbeam_doc.extend/3","doc":"extend a jsonobject by key, value","ref":"couchbeam_doc.html#extend/3"},{"type":"function","title":"couchbeam_doc.get_id/1","doc":"get document id.","ref":"couchbeam_doc.html#get_id/1"},{"type":"function","title":"couchbeam_doc.get_idrev/1","doc":"get a tuple containing docucment id and revision.","ref":"couchbeam_doc.html#get_idrev/1"},{"type":"function","title":"couchbeam_doc.get_rev/1","doc":"get document revision.","ref":"couchbeam_doc.html#get_rev/1"},{"type":"function","title":"couchbeam_doc.get_value/2","doc":"Returns the value of a simple key/value property in json object Equivalent to get_value(Key, JsonObj, undefined).","ref":"couchbeam_doc.html#get_value/2"},{"type":"function","title":"couchbeam_doc.get_value/3","doc":"Returns the value of a simple key/value property in json object function from erlang_couchdb","ref":"couchbeam_doc.html#get_value/3"},{"type":"function","title":"couchbeam_doc.is_saved/1","doc":"If document have been saved (revision is defined) return true, else, return false.","ref":"couchbeam_doc.html#is_saved/1"},{"type":"function","title":"couchbeam_doc.set_value/3","doc":"set a value for a key in jsonobj. If key exists it will be updated.","ref":"couchbeam_doc.html#set_value/3"},{"type":"function","title":"couchbeam_doc.take_value/2","doc":"Returns the value of a simple key/value property in json object and deletes it form json object Equivalent to take_value(Key, JsonObj, undefined).","ref":"couchbeam_doc.html#take_value/2"},{"type":"function","title":"couchbeam_doc.take_value/3","doc":"Returns the value of a simple key/value property in json object and deletes it from json object","ref":"couchbeam_doc.html#take_value/3"},{"type":"module","title":"couchbeam_ejson","doc":"","ref":"couchbeam_ejson.html"},{"type":"function","title":"couchbeam_ejson.decode/1","doc":"decode a binary to an EJSON term. Throw an exception if there is any error.","ref":"couchbeam_ejson.html#decode/1"},{"type":"type","title":"couchbeam_ejson.ejson/0","doc":"","ref":"couchbeam_ejson.html#t:ejson/0"},{"type":"type","title":"couchbeam_ejson.ejson_array/0","doc":"","ref":"couchbeam_ejson.html#t:ejson_array/0"},{"type":"type","title":"couchbeam_ejson.ejson_number/0","doc":"","ref":"couchbeam_ejson.html#t:ejson_number/0"},{"type":"type","title":"couchbeam_ejson.ejson_object/0","doc":"","ref":"couchbeam_ejson.html#t:ejson_object/0"},{"type":"type","title":"couchbeam_ejson.ejson_string/0","doc":"","ref":"couchbeam_ejson.html#t:ejson_string/0"},{"type":"type","title":"couchbeam_ejson.ejson_term/0","doc":"","ref":"couchbeam_ejson.html#t:ejson_term/0"},{"type":"function","title":"couchbeam_ejson.encode/1","doc":"encode an erlang term to JSON. Throw an exception if there is any error.","ref":"couchbeam_ejson.html#encode/1"},{"type":"function","title":"couchbeam_ejson.post_decode/1","doc":"","ref":"couchbeam_ejson.html#post_decode/1"},{"type":"module","title":"couchbeam_httpc","doc":"","ref":"couchbeam_httpc.html"},{"type":"type","title":"couchbeam_httpc.db/0","doc":"","ref":"couchbeam_httpc.html#t:db/0"},{"type":"function","title":"couchbeam_httpc.db_request/5","doc":"","ref":"couchbeam_httpc.html#db_request/5"},{"type":"function","title":"couchbeam_httpc.db_request/6","doc":"","ref":"couchbeam_httpc.html#db_request/6"},{"type":"function","title":"couchbeam_httpc.db_resp/2","doc":"","ref":"couchbeam_httpc.html#db_resp/2"},{"type":"function","title":"couchbeam_httpc.db_url/1","doc":"","ref":"couchbeam_httpc.html#db_url/1"},{"type":"function","title":"couchbeam_httpc.doc_url/2","doc":"","ref":"couchbeam_httpc.html#doc_url/2"},{"type":"function","title":"couchbeam_httpc.json_body/1","doc":"","ref":"couchbeam_httpc.html#json_body/1"},{"type":"function","title":"couchbeam_httpc.make_headers/4","doc":"","ref":"couchbeam_httpc.html#make_headers/4"},{"type":"function","title":"couchbeam_httpc.maybe_oauth_header/4","doc":"","ref":"couchbeam_httpc.html#maybe_oauth_header/4"},{"type":"function","title":"couchbeam_httpc.request/5","doc":"","ref":"couchbeam_httpc.html#request/5"},{"type":"type","title":"couchbeam_httpc.server/0","doc":"","ref":"couchbeam_httpc.html#t:server/0"},{"type":"function","title":"couchbeam_httpc.server_url/1","doc":"Asemble the server URL for the given client","ref":"couchbeam_httpc.html#server_url/1"},{"type":"module","title":"couchbeam_sup","doc":"","ref":"couchbeam_sup.html"},{"type":"function","title":"couchbeam_sup.init/1","doc":"","ref":"couchbeam_sup.html#init/1"},{"type":"function","title":"couchbeam_sup.start_link/0","doc":"","ref":"couchbeam_sup.html#start_link/0"},{"type":"module","title":"couchbeam_util","doc":"","ref":"couchbeam_util.html"},{"type":"function","title":"couchbeam_util.binary_env/2","doc":"","ref":"couchbeam_util.html#binary_env/2"},{"type":"function","title":"couchbeam_util.dbname/1","doc":"","ref":"couchbeam_util.html#dbname/1"},{"type":"function","title":"couchbeam_util.deprecated/3","doc":"","ref":"couchbeam_util.html#deprecated/3"},{"type":"function","title":"couchbeam_util.encode_att_name/1","doc":"","ref":"couchbeam_util.html#encode_att_name/1"},{"type":"function","title":"couchbeam_util.encode_docid1/1","doc":"","ref":"couchbeam_util.html#encode_docid1/1"},{"type":"function","title":"couchbeam_util.encode_docid/1","doc":"","ref":"couchbeam_util.html#encode_docid/1"},{"type":"function","title":"couchbeam_util.encode_docid_noop/1","doc":"","ref":"couchbeam_util.html#encode_docid_noop/1"},{"type":"function","title":"couchbeam_util.encode_query/1","doc":"Encode needed query parameter values for JSON","ref":"couchbeam_util.html#encode_query/1"},{"type":"function","title":"couchbeam_util.encode_query_value/2","doc":"Encode value in JSON if needed depending on the key","ref":"couchbeam_util.html#encode_query_value/2"},{"type":"function","title":"couchbeam_util.force_param/3","doc":"Replace a value in a property list","ref":"couchbeam_util.html#force_param/3"},{"type":"function","title":"couchbeam_util.get_app_env/2","doc":"","ref":"couchbeam_util.html#get_app_env/2"},{"type":"function","title":"couchbeam_util.get_value/2","doc":"Emulate proplists:get_value/2,3 for property lists but use faster lists:keyfind/3","ref":"couchbeam_util.html#get_value/2"},{"type":"function","title":"couchbeam_util.get_value/3","doc":"","ref":"couchbeam_util.html#get_value/3"},{"type":"function","title":"couchbeam_util.oauth_header/3","doc":"","ref":"couchbeam_util.html#oauth_header/3"},{"type":"function","title":"couchbeam_util.parse_options/1","doc":"make view options a list","ref":"couchbeam_util.html#parse_options/1"},{"type":"function","title":"couchbeam_util.parse_options/2","doc":"","ref":"couchbeam_util.html#parse_options/2"},{"type":"function","title":"couchbeam_util.propmerge1/2","doc":"Update a property list with values of the second. In case the same key is in both lists, the value from the first is kept.","ref":"couchbeam_util.html#propmerge1/2"},{"type":"function","title":"couchbeam_util.propmerge/3","doc":"Merge two property lists (lists of {Key,Value}). All the Key - Value pairs from both lists are included in the new list. If a key occurs in both dictionaries then Fun is called with the key and both values to return a new value. This a wreapper around dict:merge","ref":"couchbeam_util.html#propmerge/3"},{"type":"function","title":"couchbeam_util.proxy_header/3","doc":"","ref":"couchbeam_util.html#proxy_header/3"},{"type":"function","title":"couchbeam_util.proxy_token/2","doc":"","ref":"couchbeam_util.html#proxy_token/2"},{"type":"function","title":"couchbeam_util.shutdown_sync/1","doc":"","ref":"couchbeam_util.html#shutdown_sync/1"},{"type":"function","title":"couchbeam_util.start_app_deps/1","doc":"Start depedent applications of App.","ref":"couchbeam_util.html#start_app_deps/1"},{"type":"function","title":"couchbeam_util.to_atom/1","doc":"","ref":"couchbeam_util.html#to_atom/1"},{"type":"function","title":"couchbeam_util.to_binary/1","doc":"","ref":"couchbeam_util.html#to_binary/1"},{"type":"function","title":"couchbeam_util.to_integer/1","doc":"","ref":"couchbeam_util.html#to_integer/1"},{"type":"function","title":"couchbeam_util.to_list/1","doc":"","ref":"couchbeam_util.html#to_list/1"},{"type":"module","title":"couchbeam_uuids","doc":"","ref":"couchbeam_uuids.html"},{"type":"function","title":"couchbeam_uuids.code_change/3","doc":"","ref":"couchbeam_uuids.html#code_change/3"},{"type":"function","title":"couchbeam_uuids.get_uuids/2","doc":"Get a list of uuids from the server","ref":"couchbeam_uuids.html#get_uuids/2"},{"type":"function","title":"couchbeam_uuids.handle_call/3","doc":"","ref":"couchbeam_uuids.html#handle_call/3"},{"type":"function","title":"couchbeam_uuids.handle_cast/2","doc":"","ref":"couchbeam_uuids.html#handle_cast/2"},{"type":"function","title":"couchbeam_uuids.handle_info/2","doc":"","ref":"couchbeam_uuids.html#handle_info/2"},{"type":"function","title":"couchbeam_uuids.init/1","doc":"","ref":"couchbeam_uuids.html#init/1"},{"type":"function","title":"couchbeam_uuids.random/0","doc":"return a random uuid","ref":"couchbeam_uuids.html#random/0"},{"type":"type","title":"couchbeam_uuids.server/0","doc":"","ref":"couchbeam_uuids.html#t:server/0"},{"type":"function","title":"couchbeam_uuids.start_link/0","doc":"Starts the couchbeam process linked to the calling process. Usually invoked by the supervisor couchbeam_sup","ref":"couchbeam_uuids.html#start_link/0"},{"type":"function","title":"couchbeam_uuids.terminate/2","doc":"","ref":"couchbeam_uuids.html#terminate/2"},{"type":"function","title":"couchbeam_uuids.utc_random/0","doc":"return a random uuid based on time","ref":"couchbeam_uuids.html#utc_random/0"},{"type":"module","title":"couchbeam_view","doc":"","ref":"couchbeam_view.html"},{"type":"function","title":"couchbeam_view.all/1","doc":"Equivalent to fetch(Db, all_docs, []) . fetch all docs","ref":"couchbeam_view.html#all/1"},{"type":"function","title":"couchbeam_view.all/2","doc":"Equivalent to fetch(Db, all_docs, Options) . fetch all docs","ref":"couchbeam_view.html#all/2"},{"type":"function","title":"couchbeam_view.cancel_stream/1","doc":"","ref":"couchbeam_view.html#cancel_stream/1"},{"type":"function","title":"couchbeam_view.count/1","doc":"Equivalent to count(Db, all_docs, []) .","ref":"couchbeam_view.html#count/1"},{"type":"function","title":"couchbeam_view.count/2","doc":"Equivalent to count(Db, ViewName, []) .","ref":"couchbeam_view.html#count/2"},{"type":"function","title":"couchbeam_view.count/3","doc":"count number of doc in a view (or all docs)","ref":"couchbeam_view.html#count/3"},{"type":"type","title":"couchbeam_view.db/0","doc":"","ref":"couchbeam_view.html#t:db/0"},{"type":"type","title":"couchbeam_view.design_name/0","doc":"","ref":"couchbeam_view.html#t:design_name/0"},{"type":"type","title":"couchbeam_view.ejson_object/0","doc":"","ref":"couchbeam_view.html#t:ejson_object/0"},{"type":"function","title":"couchbeam_view.fetch/1","doc":"Equivalent to fetch(Db, all_docs, []) .","ref":"couchbeam_view.html#fetch/1"},{"type":"function","title":"couchbeam_view.fetch/2","doc":"Equivalent to fetch(Db, ViewName, []) .","ref":"couchbeam_view.html#fetch/2"},{"type":"function","title":"couchbeam_view.fetch/3","doc":"Collect view results Db: a db record ViewName: 'all_docs' to get all docs or {DesignName, ViewName} Options :: view_options() [{key, binary()}\n | {start_docid, binary()} | {startkey_docid, binary()}\n | {end_docid, binary()} | {endkey_docid, binary()}\n | {start_key, binary()} | {end_key, binary()}\n | {limit, integer()}\n | {stale, stale()}\n | descending\n | {skip, integer()}\n | group | {group_level, integer()}\n | {inclusive_end, boolean()} | {reduce, boolean()} | reduce | include_docs | conflicts\n | {keys, list(binary())}\n | async_query See couchbeam_view:stream/3 for more information about options. Return: {ok, Rows} or {error, Error}","ref":"couchbeam_view.html#fetch/3"},{"type":"function","title":"couchbeam_view.first/1","doc":"","ref":"couchbeam_view.html#first/1"},{"type":"function","title":"couchbeam_view.first/2","doc":"Equivalent to first(Db, ViewName, []) .","ref":"couchbeam_view.html#first/2"},{"type":"function","title":"couchbeam_view.first/3","doc":"get first result of a view Db: a db record ViewName: 'all_docs' to get all docs or {DesignName, ViewName} Options :: view_options() [{key, binary()}\n | {start_docid, binary()} | {startkey_docid, binary()}\n | {end_docid, binary()} | {endkey_docid, binary()}\n | {start_key, binary()} | {end_key, binary()}\n | {limit, integer()}\n | {stale, stale()}\n | descending\n | {skip, integer()}\n | group | {group_level, integer()}\n | {inclusive_end, boolean()} | {reduce, boolean()} | reduce | include_docs | conflicts\n | {keys, list(binary())} See couchbeam_view:stream/3 for more information about options. Return: {ok, Row} or {error, Error}","ref":"couchbeam_view.html#first/3"},{"type":"function","title":"couchbeam_view.fold/4","doc":"Equivalent to fold(Function, Acc, Db, ViewName, []) .","ref":"couchbeam_view.html#fold/4"},{"type":"function","title":"couchbeam_view.fold/5","doc":"call Function(Row, AccIn) on succesive row, starting with AccIn == Acc. Function/2 must return a new list accumultator or the atom done to stop fetching results. Acc0 is returned if the list is empty. For example: couchbeam_view:fold(fun(Row, Acc) -> [Row|Acc] end, [], Db, 'all_docs').","ref":"couchbeam_view.html#fold/5"},{"type":"function","title":"couchbeam_view.foreach/3","doc":"Equivalent to foreach(Function, Db, ViewName, []) .","ref":"couchbeam_view.html#foreach/3"},{"type":"function","title":"couchbeam_view.foreach/4","doc":"call Function(Row) on succesive row. Example: couchbeam_view:foreach(fun(Row) -> io:format("got row ~p~n", [Row]) end, Db, 'all_docs').","ref":"couchbeam_view.html#foreach/4"},{"type":"function","title":"couchbeam_view.parse_view_options/1","doc":"parse view options","ref":"couchbeam_view.html#parse_view_options/1"},{"type":"type","title":"couchbeam_view.server/0","doc":"","ref":"couchbeam_view.html#t:server/0"},{"type":"function","title":"couchbeam_view.show/2","doc":"","ref":"couchbeam_view.html#show/2"},{"type":"function","title":"couchbeam_view.show/3","doc":"","ref":"couchbeam_view.html#show/3"},{"type":"function","title":"couchbeam_view.show/4","doc":"","ref":"couchbeam_view.html#show/4"},{"type":"type","title":"couchbeam_view.show_option/0","doc":"example: \"foo=bar&baz=biz\"","ref":"couchbeam_view.html#t:show_option/0"},{"type":"type","title":"couchbeam_view.show_options/0","doc":"","ref":"couchbeam_view.html#t:show_options/0"},{"type":"type","title":"couchbeam_view.stale/0","doc":"","ref":"couchbeam_view.html#t:stale/0"},{"type":"function","title":"couchbeam_view.stream/2","doc":"Equivalent to stream(Db, ViewName, []) .","ref":"couchbeam_view.html#stream/2"},{"type":"function","title":"couchbeam_view.stream/3","doc":"stream view results to a pid Db: a db record ViewName: 'all_docs' to get all docs or {DesignName, ViewName} Client receives messages: - {row, StartRef, done} All rows have been fetched - {row, StartRef, Row :: ejson_object()} A row in the view - {error, StartRef, Error} An error occurred; stream closed Options include (see couchbeam_view:parse_view_options/1): - {key, Key} - {start_docid, DocId} | {startkey_docid, DocId} - {end_docid, DocId} | {endkey_docid, DocId} - {start_key, Key} | {end_key, Key} - {limit, N} - {stale, ok | update_after | false} - descending | {skip, N} - group | {group_level, integer()} - reduce | {reduce, boolean()} - include_docs | conflicts | {inclusive_end, boolean()} - {keys, [Key]} - {stream_to, Pid}","ref":"couchbeam_view.html#stream/3"},{"type":"function","title":"couchbeam_view.stream_next/1","doc":"","ref":"couchbeam_view.html#stream_next/1"},{"type":"type","title":"couchbeam_view.view_name/0","doc":"","ref":"couchbeam_view.html#t:view_name/0"},{"type":"type","title":"couchbeam_view.view_option/0","doc":"","ref":"couchbeam_view.html#t:view_option/0"},{"type":"type","title":"couchbeam_view.view_options/0","doc":"","ref":"couchbeam_view.html#t:view_options/0"},{"type":"type","title":"couchbeam_view.view_query_args/0","doc":"","ref":"couchbeam_view.html#t:view_query_args/0"},{"type":"module","title":"couchbeam_view_stream","doc":"","ref":"couchbeam_view_stream.html"},{"type":"function","title":"couchbeam_view_stream.init_stream/5","doc":"","ref":"couchbeam_view_stream.html#init_stream/5"},{"type":"function","title":"couchbeam_view_stream.maybe_continue/1","doc":"","ref":"couchbeam_view_stream.html#maybe_continue/1"},{"type":"function","title":"couchbeam_view_stream.start_link/4","doc":"","ref":"couchbeam_view_stream.html#start_link/4"},{"type":"function","title":"couchbeam_view_stream.system_code_change/4","doc":"","ref":"couchbeam_view_stream.html#system_code_change/4"},{"type":"function","title":"couchbeam_view_stream.system_continue/3","doc":"","ref":"couchbeam_view_stream.html#system_continue/3"},{"type":"function","title":"couchbeam_view_stream.system_terminate/4","doc":"","ref":"couchbeam_view_stream.html#system_terminate/4"},{"type":"module","title":"couchbeam_view_sup","doc":"","ref":"couchbeam_view_sup.html"},{"type":"function","title":"couchbeam_view_sup.init/1","doc":"","ref":"couchbeam_view_sup.html#init/1"},{"type":"function","title":"couchbeam_view_sup.start_link/0","doc":"","ref":"couchbeam_view_sup.html#start_link/0"},{"type":"behaviour","title":"gen_changes","doc":"gen_changes CouchDB continuous changes consumer behavior This behaviour allows you to create easily a server that consume Couchdb continuous changes","ref":"gen_changes.html"},{"type":"function","title":"gen_changes.behaviour_info/1","doc":"","ref":"gen_changes.html#behaviour_info/1"},{"type":"function","title":"gen_changes.call/2","doc":"","ref":"gen_changes.html#call/2"},{"type":"function","title":"gen_changes.call/3","doc":"","ref":"gen_changes.html#call/3"},{"type":"function","title":"gen_changes.cast/2","doc":"","ref":"gen_changes.html#cast/2"},{"type":"function","title":"gen_changes.code_change/3","doc":"","ref":"gen_changes.html#code_change/3"},{"type":"function","title":"gen_changes.get_seq/1","doc":"","ref":"gen_changes.html#get_seq/1"},{"type":"function","title":"gen_changes.handle_call/3","doc":"","ref":"gen_changes.html#handle_call/3"},{"type":"function","title":"gen_changes.handle_cast/2","doc":"","ref":"gen_changes.html#handle_cast/2"},{"type":"function","title":"gen_changes.handle_info/2","doc":"","ref":"gen_changes.html#handle_info/2"},{"type":"function","title":"gen_changes.init/1","doc":"","ref":"gen_changes.html#init/1"},{"type":"function","title":"gen_changes.start_link/4","doc":"create a gen_changes process as part of a supervision tree. The function should be called, directly or indirectly, by the supervisor. InitArgs::list()) -> term() changesoptions() = [changeoption()] changeoption() = {include_docs, string()} | {filter, string()} | {since, integer()|string()} | {heartbeat, string()|boolean()}","ref":"gen_changes.html#start_link/4"},{"type":"function","title":"gen_changes.stop/1","doc":"","ref":"gen_changes.html#stop/1"},{"type":"function","title":"gen_changes.terminate/2","doc":"","ref":"gen_changes.html#terminate/2"},{"type":"module","title":"json_stream_parse","doc":"","ref":"json_stream_parse.html"},{"type":"function","title":"json_stream_parse.feed/2","doc":"","ref":"json_stream_parse.html#feed/2"},{"type":"function","title":"json_stream_parse.finish/1","doc":"","ref":"json_stream_parse.html#finish/1"},{"type":"function","title":"json_stream_parse.init/0","doc":"","ref":"json_stream_parse.html#init/0"},{"type":"extras","title":"Readme","doc":"# Couchbeam - simple Apache CouchDB client library for Erlang applications #\n\nCopyright (c) 2009-2025 Benoit Chesneau.\n\n__Version:__ 1.7.1\n\n# couchbeam\n\nCouchbeam is a simple erlang library for [Barrel](https://barrel-db.org) or [Apache CouchDB](http://couchdb.apache.org). Couchbeam provides you a full featured and easy client to access and manage multiple nodes.\n\n#### Main features:\n\n- Complete support of the BarrelDB and Apache CouchDB API\n- Stream view results to your app\n- Stream changes feeds\n- reduced memory usage\n- fetch and send attachments in a streaming fashion\n- JSON encoding/decoding via Erlang/OTP stdlib `json` with maps\n\n#### Useful modules are:\n\n- [`couchbeam`](http://github.com/benoitc/couchbeam/blob/master/doc/couchbeam.md): The `couchbeam` module is the main interface for interaction with this application. It includes functions for managing connections to Apache CouchDB or RCOUCH servers and databases and for performing document creations, updates, deletes, views...\n- [`couchbeam_doc`](http://github.com/benoitc/couchbeam/blob/master/doc/couchbeam_doc.md) Module to manipulate Documents structures. You can set values,\nupdates keys, ...\n- [`couchbeam_attachments`](http://github.com/benoitc/couchbeam/blob/master/doc/couchbeam_attachments.md): Module to manipulate attachments. You can add, remove\nattachments in a Document structure (inline attachments).\n- [`couchbeam_view`](http://github.com/benoitc/couchbeam/blob/master/doc/couchbeam_view.md): Module to manage view results.\n- [`couchbeam_changes`](http://github.com/benoitc/couchbeam/blob/master/doc/couchbeam_changes.md): Module to manage changes feeds. Follow continuously\nthe changes in a db or get all changes at once.\n\nThe goal of Couchbeam is to ease the access to the Apache CouchDB and RCOUCH HTTP API in erlang.\n\nRead the [NEWS](https://raw.github.com/benoitc/couchbeam/master/NEWS) file\nto get last changelog.","ref":"readme.html"},{"type":"extras","title":"Installation - Readme","doc":"Download the sources from our [Github repository](http://github.com/benoitc/couchbeam)\n\nTo build the application simply run 'make'. This should build .beam, .app\nfiles and documentation.\n\nTo run tests run 'make test'.\nTo generate doc, run 'make doc'.\n\nOr add it to your rebar config\n\n```\n erlang\n{deps, [\n ....\n {couchbeam, \".*\", {git, \"git://github.com/benoitc/couchbeam.git\", {branch, \"master\"}}}\n]}.\n```\n\nNote to compile with jiffy you need to define in the erlang options the\nvariable `WITH_JIFFY`.\n\nif you use rebar, add to your `rebar.config`:\n\n```\n erlang\n{erl_opts, [{d, 'WITH_JIFFY'}]}.\n```\n\nor use the `rebar` command with the `-D` options:\n\n```\n sh\nrebar compile -DWITH_JIFFY\n```","ref":"readme.html#installation"},{"type":"extras","title":"Basic Usage - Readme","doc":"","ref":"readme.html#basic-usage"},{"type":"extras","title":"Start couchbeam - Readme","doc":"Couchbeam is an [OTP](http://www.erlang.org/doc/design_principles/users_guide.html)\napplication. You have to start it first before using any of the\nfunctions. The couchbeam application will start the default socket pool\nfor you.\n\nTo start in the console run:\n\n```\n sh\n$ erl -pa ebin\n1> couchbeam:start().\nok\n```\n\nIt will start hackney and all of the application it depends on:\n\n```\n erlang\napplication:start(crypto),\napplication:start(asn1),\napplication:start(public_key),\napplication:start(ssl),\napplication:start(hackney),\napplication:start(couchbeam).\n```\n\nOr add couchbeam to the applications property of your .app in a release","ref":"readme.html#start-couchbeam"},{"type":"extras","title":"Create a connection to the server - Readme","doc":"To create a connection to a server machine:\n\n```\n erlang\nUrl = \"http://localhost:5984\",\nOptions = [],\nS = couchbeam:server_connection(Url, Options).\n```\n\nTest the connection with `couchbeam:server_info/1` :\n\n```\n erlang\n{ok, _Version} = couchbeam:server_info(S).\n```","ref":"readme.html#create-a-connection-to-the-server"},{"type":"extras","title":"Open or Create a database - Readme","doc":"All document operations are done in databases. To open a database simply do:\n\n```\n erlang\nOptions = [],\n{ok, Db} = couchbeam:open_db(Server, \"testdb\", Options).\n```\n\nTo create a new one:\n\n```\n erlang\nOptions = [],\n{ok, Db} = couchbeam:create_db(Server, \"testdb\", Options).\n```\n\nYou can also use the shorcut `couchbeam:open_or_create_db/3`. that\nwill create a database if it does not exist.","ref":"readme.html#open-or-create-a-database"},{"type":"extras","title":"Make a new document - Readme","doc":"Make a new document:\n\n```\n erlang\nDoc = #{\n <<\"_id\">> => <<\"test\">>,\n <<\"content\">> => <<\"some text\">>\n}.\n```\n\nAnd save it to the database:\n\n```\n erlang\n{ok, Doc1} = couchbeam:save_doc(Db, Doc).\n```\n\nThe `couchbeam:save_doc/2` return a new document with updated\nrevision and if you do not specify the _id, a unique document id.\n\nTo change an document property use functions from `couchbeam_doc`.","ref":"readme.html#make-a-new-document"},{"type":"extras","title":"Retrieve a document - Readme","doc":"To retrieve a document do:\n\n```\n erlang\n{ok, Doc2} = couchbeam:open_doc(Db, \"test\").\n```\n\nIf you want a specific revision:\n\n```\n erlang\nRev = couchbeam_doc:get_rev(Doc1),\nOptions = [{rev, Rev}],\n{ok, Doc3} = couchbeam:open_doc(Db, \"test\", Options).\n```\n\nHere we get the revision from the document we previously stored. Any\noptions from the Apache CouchDB and RCOUCH API can be used.","ref":"readme.html#retrieve-a-document"},{"type":"extras","title":"Get all documents - Readme","doc":"To get all documents you have first to create an object\nthat will keep all informations.\n\n```\n erlang\nOptions = [include_docs],\n{ok, AllDocs} = couchbeam_view:all(Db, Options).\n```\n\nExample result (abridged):\n\n```\n erlang\n{ok, [\n #{\n <<\"id\">> => <<\"7a0ce91d0d0c5e5b51e904d1ee3266a3\">>,\n <<\"key\">> => <<\"7a0ce91d0d0c5e5b51e904d1ee3266a3\">>,\n <<\"value\">> => #{<<\"rev\">> => <<\"15-15c0b3c4efa74f9a80d28ac040f18bdb\">>},\n <<\"doc\">> => #{\n <<\"_id\">> => <<\"7a0ce91d0d0c5e5b51e904d1ee3266a3\">>,\n <<\"_rev\">> => <<\"15-15c0b3c4efa74f9a80d28ac040f18\"...>>\n }\n }\n]}.\n```\n\nAll functions to manipulate these results are in the `couchbeam_view` module.","ref":"readme.html#get-all-documents"},{"type":"extras","title":"Couch DB views - Readme","doc":"Views are workin like all_docs. You have to create a View object before\ndoing anything.\n\n```\n erlang\nOptions = [],\nDesignName = \"designname\",\nViewName = \"viewname\",\n{ok, ViewResults} = couchbeam_view:fetch(Db, {DesignName, ViewName}, Options).\n```\n\nLike the `all_docs` function, use the functions\nfrom `couchbeam_view` module to manipulate results. You can pass\nany querying options from the [view API](http://docs.rcouch.org/en/latest/api/ddoc/views.html).\n\nDesign doc are created like any documents:\n\n```\n erlang\nDesignDoc = #{\n <<\"_id\">> => <<\"_design/couchbeam\">>,\n <<\"language\">> => <<\"javascript\">>,\n <<\"views\">> => #{\n <<\"test\">> => #{\n <<\"map\">> => <<\"function (doc) {\\n if (doc.type == \\\"test\\\") {\\n emit(doc._id, doc);\\n}\\n}\">>\n },\n <<\"test2\">> => #{\n <<\"map\">> => <<\"function (doc) {\\n if (doc.type == \\\"test2\\\") {\\n emit(doc._id, null);\\n}\\n}\">>\n }\n }\n},\n{ok, DesignDoc1} = couchbeam:save_doc(Db, DesignDoc).\n```\n\nYou can also use [couchapp](http://github.com/couchapp/couchapp) to manage them\nmore easily.","ref":"readme.html#couch-db-views"},{"type":"extras","title":"Stream View results - Readme","doc":"While you can get results using `couchbeam_views:fetch/2`, you can also retrieve\nall rows in a streaming fashion:\n\n```\n erlang\nViewFun = fun(Ref, F) ->\n receive\n {Ref, done} ->\n io:format(\"done\", []),\n done;\n {Ref, {row, Row}} ->\n io:format(\"got ~p~n\", [Row]),\n F(Ref, F);\n {error, Ref, Error} ->\n io:format(\"error: ~p~n\", [Error])\n end\nend,\n\n{ok, StreamRef} = couchbeam_view:stream(Db, 'all_docs'),\nViewFun(StreamRef, ViewFun),\n{ok, StreamRef2} = couchbeam_view:stream(Db, 'all_docs', [include_docs]),\nViewFun(StreamRef2, ViewFun).\n```\n\nYou can of course do the same with a view:\n\n```\n erlang\nDesignNam = \"designname\",\nViewName = \"viewname\",\n{ok, StreamRef3} = couchbeam_view:stream(Db, {DesignNam, ViewName}, [include_docs]),\nViewFun(StreamRef3, ViewFun).\n```","ref":"readme.html#stream-view-results"},{"type":"extras","title":"Put, Fetch and Delete documents attachments - Readme","doc":"You can add attachments to any documents. Attachments could be anything.\n\nTo send an attachment:\n\n```\n erlang\nDocID = \"test\",\nAttName = \"test.txt\",\nAtt = \"some content I want to attach\",\nOptions = []\n{ok, _Result} = couchbeam:put_attachment(Db, DocId, AttName, Att, Options).\n```\n\nAll attachments are streamed to servers. `Att` could be also be an iolist\nor functions, see `couchbeam:put_attachment/5` for more information.\n\nTo fetch an attachment:\n\n```\n erlang\n{ok Att1} = couchbeam:fetch_attachment(Db, DocId, AttName).\n```\n\nYou can use `couchbeam:stream_attachment/1` for the stream\nfetch.\n\nTo delete an attachment:\n\n```\n erlang\n{ok, Doc4} = couchbeam:open_doc(Db, DocID),\nok = couchbeam:delete_attachment(Db, Doc4, AttName).\n```","ref":"readme.html#put-fetch-and-delete-documents-attachments"},{"type":"extras","title":"Changes - Readme","doc":"Apache CouchDB and RCOUCH provide a means to get a list of changes made to documents in\nthe database. With couchbeam you can get changes using `couchbeam_changes:follow_once/2`.\nThis function returns all changes immediately. But you can also retrieve\nall changes rows using longpolling :\n\n```\n erlang\nOptions = [],\n{ok, LastSeq, Rows} = couchbeam_changes:follow_once(Db, Options).\n```\n\nOptions can be any Changes query parameters. See the [change API](http://docs.rcouch.org/en/latest/api/database/changes.html) for more informations.\n\nYou can also get [continuous](http://docs.rcouch.org/en/latest/api/database/changes.html#continuous):\n\n```\n erlang\nChangesFun = fun(StreamRef, F) ->\n receive\n {StreamRef, {done, LastSeq}} ->\n io:format(\"stopped, last seq is ~p~n\", [LastSeq]),\n ok;\n {StreamRef, {change, Change}} ->\n io:format(\"change row ~p ~n\", [Change]),\n F(StreamRef, F);\n {StreamRef, Error}->\n io:format(\"error ? ~p ~n,\", [Error])\n end\nend,\nOptions = [continuous, heartbeat],\n{ok, StreamRef} = couchbeam_changes:follow(Db, Options),\nChangesFun(StreamRef, ChangesFun).\n```\n\n> **Note**: a `gen_changes` behaviour exists in couchbeam that you can\nuse to create your own specific gen_server receiving changes. Have a\nlook in the\n[example](https://github.com/benoitc/couchbeam/blob/master/examples/test_gen_changes.erl)\nfor more info.","ref":"readme.html#changes"},{"type":"extras","title":"Authentication/ Connections options - Readme","doc":"You can authenticate to the database or Apache CouchDB or RCOUCH server by filling\noptions to the Option list in `couchbeam:server_connection/4` for the\nserver or in `couchbeam:create_db/3`, `couchbeam:open_db/3`,\n`couchbeam:open_or_create_db/3` functions.\n\nTo set basic_auth on a server:\n\n```\n erlang\nUserName = \"guest\",\nPassword = \"test\",\nUrl = \"http://localhost:5984\",\nOptions = [{basic_auth, {UserName, Password}}],\nS1 = couchbeam:server_connection(Url, Options).\n```\n\nCouchbeam support SSL, OAuth, Basic Authentication, and Proxy. You can\nalso set a cookie. For more informations about the options have a look\nin the `couchbeam:server_connection/2` documentation.","ref":"readme.html#authentication-connections-options"},{"type":"extras","title":"Contribute - Readme","doc":"For issues, comments or feedback please [create an\nissue](http://github.com/benoitc/couchbeam/issues).","ref":"readme.html#contribute"},{"type":"extras","title":"Changelog","doc":"couchbeam NEWS\n--------------\n\nversion 2.0.0 / 2025-09-03\n--------------------------\n\n- move from propos lists to maps for json\n- remove JSX & Jiffy Usage for erlang/0TP 28.0+ json module\n- View and changes streaming now use a simpler parser\n\n** BREAKING CHANGE **\n\n- move to maps, you will need to migrate your application to use them. \nno backward compatibility is provided\n\nversion 1.7.1 / 2025-07-24\n---------------------------\n\n- update hackney depdendency to 1.25.0\n\nversion 1.7.0 / 2025-05-28\n--------------------------\n\n- fix resource leaks and race conditions in stream modules\n- fix unclosed hackney connections on error paths\n- add proper cleanup for monitor references using try-finally\n- fix ETS table race conditions by checking process liveness\n- improve stream initialization order to prevent races\n- add error handling for hackney operations to prevent leaks\n- fix changes stream registration race condition by registering before parent notification\n\nversion 1.6.0 / 2025-01-26\n--------------------------\n\n- add support for CouchDB _find endpoint\n- add ability to query _show functions \n- add option for disabling view_stream usage (enabled by default)\n- fix error handling in gen_changes callback handling\n- fix resource cleanup in stream modules to prevent connection leaks\n- improve replication test reliability and timeout handling\n- update hackney dependency to 1.23\n- update jsx dependency\n- add GitHub Actions for CouchDB testing\n- fix dialyzer complaints and pattern matching issues\n- OTP 27 compatibility improvements\n\nversion 1.5.4 / 2025-02-20\n--------------------------\n\n- bump hackney 1.22.0\n\nversion 1.5.3 / 2024-08-20\n--------------------------\n\n- fix packaging\n\nversion 1.5.1 / 2024-11-07\n--------------------------\n\n- fix pattern matching\n\nversion 1.5.1 / 2024-11-07\n--------------------------\n\n- fix: handle condition that may cause persistent CLOSE-WAIT sockets\n\nversion 1.5.0 / 2023-10-11\n--------------------------\n\n- use hackney 1.20.0\n- fix compatibility with couchdb 3\n- fix compatibility with Erlang >= 23\n\nversion 1.4.1 / 2016-09-26\n--------------------------\n\n- maintainance update\n\nversion 1.4.0 / 2016-09-22\n--------------------------\n\n- maintainance update.\n\nversion 1.3.1 / 2016-07-01\n--------------------------\n\n- fix: accept 202 status in `couchbeam:save_doc/4` function (#144)\n- fix: spec syntax to build with Erlang 19 (#145)\n\nversion 1.3.0 / 2016-03-22\n--------------------------\n\n- add `couchbeam:all_dbs/2`\n- add `couchbeam:view_cleanup/1`\n- add `couchbeam:design_info/2`\n- add `post_decode` function to view stream\n- add Elixir mix support\n- fix: handle http errors in view stream (#140)\n- fix: build with latest rebar3\n\nversion 1.2.1 / 2015/11/04\n--------------------------\n\n- also support hackney 1.4.4 for rebar2.\n- fix hex.pm release to really use 1.4.4\n\nversion 1.2.0 / 2015/11/04\n--------------------------\n\n- move to eunit for tests.\n- hex.pm support\n- mix & rebar3 build tools support\n- bump hackney to 1.4.4\n- bump jsx to 2.2.8","ref":"news.html"},{"type":"extras","title":"Breaking change - Changelog","doc":"erlang-oauth is now optionnal and won't be installed by default.\n\nversion 1.1.8 / 2015-08-27\n--------------------------\n\n- use latest stable branch of [hackney](https://github.com/benoitc/hackney)\n\nversion 1.1.7 / 2015-03-11\n--------------------------\n\n- bump [hackney](https://github.com/benoitc/hackney) to 1.1.0\n- fix `Conten-Type` header ehen posting doc IDS in changes #126\n- fix documentation\n\nversion 1.1.6 / 2015-01-02\n--------------------------\n\n- fix `included_applications` (#122)\n\nversion 1.1.5 / 2014-12-09\n--------------------------\n\n- improvement: do not force connections options to nodelay\n- update to [Hackney](https://github.com/benoitc/hackney) 1.0.4 fix #120\n- fix: retry fecthing UUIDS on error (#121)\n\nversion 1.1.4 / 2014-12-01\n--------------------------\n\n- update to [Hackney](https://github.com/benoitc/hackney) 1.0.1: more SSL\n certificate authority handling.\n- fix: changes stream\n\nversion 1.1.3 / 2014-11-30\n--------------------------\n\n- update to [Hackney](https://github.com/benoitc/hackney) 1.0.0\n\nversion 1.1.2 / 2014-11-15\n--------------------------\n\n- remove spurious prints\n\nversion 1.1.1 / 2014-11-11\n--------------------------\n\n- update to [hackney 0.15.0](https://github.com/benoitc/hackney/releases ),\n improving performances and concurrency\n- fix `couchbeam:doc_exists/2`(#116)\n- fix `couchbeam:reply_att/1` (#114)\n\n\nversion 1.1.0 / 2014-10-28\n--------------------------\n\n- update to [hackney 0.14.3](https://github.com/benoitc/hackney/releases)\n- fix memory leaks\n- correctly close sockets\n- fix streaming issue: don't wait the stream timeout to report the initial\n error.\n- update JSX dependency to version 2.1.1\n\nversion 1.0.7 / 2014-07-08\n--------------------------\n\n- bump to [hackney 0.13.0](https://github.com/benoitc/hackney/releases/tag/0.13.0)\n\nversion 1.0.6 / 2014-04-18\n--------------------------\n\n- bump to [hackney 0.12.1](https://github.com/benoitc/hackney/releases/tag/0.12.2)\n\n\nversion 1.0.5 / 2014-04-18\n--------------------------\n\n- improve connections with HTTP proxies\n- improve content-types detection of attachments\n- improve URL encoding normalzation, useful when connecting to an\n international domain/URI\n- URL resolving is faster\n- bump to [hackney 0.12.0](https://github.com/benoitc/hackney/releases/tag/0.12.0)\n\nversion 1.0.4 / 2014-04-15\n--------------------------\n\n- remove spurious print\n\nversion 1.0.3 / 2014-04-15\n--------------------------\n\n- add support for the `new_edits` option in bulk doc API.\n- improvement: send a doc as multipart that already contains attachments\n- bump [hackney](http://github.com/benoitc/hackney) to 0.11.2\n- fix path encoding\n\nversion 1.0.2 / 2014-01-03\n--------------------------\n\n- fix: send a doc as multipart that already contains attachments\n\n\nversion 1.0.1 / 2013-12-30\n--------------------------\n\n- fix connection reusing in changes and view streams\n- bump hackney version to 0.10.1\n\n\nversion 1.0.0 / 2013-12-21\n--------------------------\n\n**First stable release**. This is a supported release.\n\n- send a doc and its attachments efficiently using the [multipart\n API](http://docs.couchdb.org/en/latest/api/document/common.html#creating-multiple-attachments).\n- add `couchbeam:get_config/{1,2,3}`, `couchbeam:set_config/{4,5}` and\n `couchbeam:delete_config/{3,4}` to use the [config\nAPI](http://docs.couchdb.org/en/latest/api/server/configuration.html).\n- add `couchbeam_uuids:random/0` and `couchbeam_uuids:utc_random/0` to\n generate UUIDS in your app instead of reusing the UUID generated on\nthe node. By default couchbeam is fetching from the node, which is\n- add `{error, forbidden}` and `{error, unauthenticated}` as possible\n results of a reply.\nbetter if you want to use UUID based on the node time.\n- fix accept header handling\n\n\nversion 0.10.0 / 2013-12-21\n---------------------------\n\n- add `couchbeam:copy_doc/{2,3}` to support the COPY API\n- add `couchbeam:get_missing_revs/2` to get the list of missing\n revisions\n- add support of the [multipart\n API](http://docs.couchdb.org/en/latest/api/document/common.html#efficient-multiple-attachments-retrieving) when fetching a doc: This change make\n `couchbeam:open_doc/3` returns a multipart response `{ok, {multipart, Stream}}`\n when using the `attachments=true` option. A new option `{accept, <<\"multipart/mixed\">>}`\n can also be used with the options `open_revs` or `revs` to fetch the response as a multipart.\n- bump the [hackney](http://github.com/benoitc/hackney) version to\n **0.9.1** .\n\n\nWith this change you can now efficiently retrieve a doc with all of its\nattachments or a doc wit all its revisions.\n master\n\nversion 0.9.3 / 2013-12-07\n--------------------------\n\n- fix: couchbeam:open_or_create_db/2\n\nversion 0.9.2 / 2013-12-07\n--------------------------\n\n- bump hackney version to 0.8.3\n\nversion 0.9.1 / 2013-12-05\n--------------------------\n\n- fix design docid encoding\n\nversion 0.9.0 / 2013-12-05\n--------------------------\n\nThis is a major release pre-1.0. API is now frozen and won't change much\nuntil the version 1.0.\n\n- replaced the use of ibrowse by hackney to handle HTTP connections\n- new [streaming\n API](https://github.com/benoitc/couchbeam#stream-view-results) in view\n- breaking change: remobe\n- breaking change: remove deprecated view API. Everything is now managed in the\n [couch_view](https://github.com/benoitc/couchbeam/blob/master/doc/couchbeam_view.md) module.\n- replace 'couchbeam_changes:stream' and 'couchbeam_changes:fetch'\n functions by 'couchbeam_changes/follow' and 'couchbeam_changes:follow_once'.\n- breaking change: new attachment API\n- new: JSX a pure erlang JSON encoder/decoder is now the default. Jiffy\n can be set at the compilation by defining 'WITH_JIFFY' in the Erlang\noptions.\n- removed mochiweb dependency.\n\n\nversion 0.7.0 / 2011-07-05\n--------------------------\n\nThis release contains backwards incompatible changes.\n\n- New and more efficient couchbeam_changes API, we now parse json stream\n instead of the try catch steps we used before.\n- New and more efficient couchbeam_view API. we now parse json stream\n instead of getting all results. New couchbeam_view:stream and\ncouchbeam_view fetch functions have been added. We also don't use any\nmore a view record in other functions\n- HTTP functions have been moved to couchbeam_httpc modules\n- gen_changes behaviour has been updated to use the couchbeam_changes\n API. It's also abble to restart a lost connection for longpoll and\ncontinuous feeds.\n\nBreaking Changes:\n\n- couchbeam:view and couchbeam:all_docs have been deprecated. Old views\n functions using the #view{} record from these functions have been\nmoved in couchbeam_oldview module.\n- couchbeam:wait_changes, couchbeam:wait_changes_once, couchbeam:changes\n functions have been deprecated and are now replaced by\ncouchbeam_changes:stream and couchbeam_changes:fetch functions.","ref":"news.html#breaking-change"},{"type":"extras","title":"Notice","doc":"Couchbeam\n---------\n\n2009-2025 (c) Benoit Chesneau\n\ncouchbeam is released under the MIT license. See the LICENSE file for the\ncomplete license.","ref":"notice.html"},{"type":"extras","title":"License","doc":"2009-2025 (c) Benoit Chesneau\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.","ref":"license.html"}],"proglang":"erlang","content_type":"text/markdown","producer":{"name":"ex_doc","version":"0.38.2"}} \ No newline at end of file diff --git a/site/dist/sidebar_items-A03F7C15.js b/site/dist/sidebar_items-A03F7C15.js new file mode 100644 index 00000000..41e74657 --- /dev/null +++ b/site/dist/sidebar_items-A03F7C15.js @@ -0,0 +1 @@ +sidebarNodes={"modules":[{"id":"couchbeam","deprecated":false,"group":"","title":"couchbeam","sections":[],"nodeGroups":[{"name":"Types","nodes":[{"id":"db/0","deprecated":false,"title":"db/0","anchor":"t:db/0"},{"id":"doc/0","deprecated":false,"title":"doc/0","anchor":"t:doc/0"},{"id":"doc_stream/0","deprecated":false,"title":"doc_stream/0","anchor":"t:doc_stream/0"},{"id":"ejson_object/0","deprecated":false,"title":"ejson_object/0","anchor":"t:ejson_object/0"},{"id":"mp_attachment/0","deprecated":false,"title":"mp_attachment/0","anchor":"t:mp_attachment/0"},{"id":"mp_attachments/0","deprecated":false,"title":"mp_attachments/0","anchor":"t:mp_attachments/0"},{"id":"server/0","deprecated":false,"title":"server/0","anchor":"t:server/0"}],"key":"types"},{"name":"Functions","nodes":[{"id":"all_dbs/1","deprecated":false,"title":"all_dbs(Server)","anchor":"all_dbs/1"},{"id":"all_dbs/2","deprecated":false,"title":"all_dbs(Server, Options)","anchor":"all_dbs/2"},{"id":"compact/1","deprecated":false,"title":"compact(Db)","anchor":"compact/1"},{"id":"compact/2","deprecated":false,"title":"compact(Db, DesignName)","anchor":"compact/2"},{"id":"copy_doc/2","deprecated":false,"title":"copy_doc(Db, Doc)","anchor":"copy_doc/2"},{"id":"copy_doc/3","deprecated":false,"title":"copy_doc(Db, Doc, Dest)","anchor":"copy_doc/3"},{"id":"create_db/2","deprecated":false,"title":"create_db(Server, DbName)","anchor":"create_db/2"},{"id":"create_db/3","deprecated":false,"title":"create_db(Server, DbName, Options)","anchor":"create_db/3"},{"id":"create_db/4","deprecated":false,"title":"create_db(Server, DbName0, Options, Params)","anchor":"create_db/4"},{"id":"db_exists/2","deprecated":false,"title":"db_exists(Server, DbName)","anchor":"db_exists/2"},{"id":"db_info/1","deprecated":false,"title":"db_info(Db)","anchor":"db_info/1"},{"id":"delete_attachment/3","deprecated":false,"title":"delete_attachment(Db, Doc, Name)","anchor":"delete_attachment/3"},{"id":"delete_attachment/4","deprecated":false,"title":"delete_attachment(Db, DocOrDocId, Name, Options)","anchor":"delete_attachment/4"},{"id":"delete_db/1","deprecated":false,"title":"delete_db(Db)","anchor":"delete_db/1"},{"id":"delete_db/2","deprecated":false,"title":"delete_db(Server, DbName)","anchor":"delete_db/2"},{"id":"delete_doc/2","deprecated":false,"title":"delete_doc(Db, Doc)","anchor":"delete_doc/2"},{"id":"delete_doc/3","deprecated":false,"title":"delete_doc(Db, Doc, Options)","anchor":"delete_doc/3"},{"id":"delete_docs/2","deprecated":false,"title":"delete_docs(Db, Docs)","anchor":"delete_docs/2"},{"id":"delete_docs/3","deprecated":false,"title":"delete_docs(Db, Docs, Options)","anchor":"delete_docs/3"},{"id":"design_info/2","deprecated":false,"title":"design_info(Db, DesignName)","anchor":"design_info/2"},{"id":"doc_exists/2","deprecated":false,"title":"doc_exists(Db, DocId)","anchor":"doc_exists/2"},{"id":"end_doc_stream/1","deprecated":false,"title":"end_doc_stream(_)","anchor":"end_doc_stream/1"},{"id":"ensure_full_commit/1","deprecated":false,"title":"ensure_full_commit(Db)","anchor":"ensure_full_commit/1"},{"id":"ensure_full_commit/2","deprecated":false,"title":"ensure_full_commit(Db, Options)","anchor":"ensure_full_commit/2"},{"id":"fetch_attachment/3","deprecated":false,"title":"fetch_attachment(Db, DocId, Name)","anchor":"fetch_attachment/3"},{"id":"fetch_attachment/4","deprecated":false,"title":"fetch_attachment(Db, DocId, Name, Options0)","anchor":"fetch_attachment/4"},{"id":"find/3","deprecated":false,"title":"find(Db, Selector, Params)","anchor":"find/3"},{"id":"get_missing_revs/2","deprecated":false,"title":"get_missing_revs(Db, IdRevs)","anchor":"get_missing_revs/2"},{"id":"get_uuid/1","deprecated":false,"title":"get_uuid(Server)","anchor":"get_uuid/1"},{"id":"get_uuids/2","deprecated":false,"title":"get_uuids(Server, Count)","anchor":"get_uuids/2"},{"id":"lookup_doc_rev/2","deprecated":false,"title":"lookup_doc_rev(Db, DocId)","anchor":"lookup_doc_rev/2"},{"id":"lookup_doc_rev/3","deprecated":false,"title":"lookup_doc_rev(Db, DocId, Params)","anchor":"lookup_doc_rev/3"},{"id":"open_db/2","deprecated":false,"title":"open_db(Server, DbName)","anchor":"open_db/2"},{"id":"open_db/3","deprecated":false,"title":"open_db(Server, DbName, Options)","anchor":"open_db/3"},{"id":"open_doc/2","deprecated":false,"title":"open_doc(Db, DocId)","anchor":"open_doc/2"},{"id":"open_doc/3","deprecated":false,"title":"open_doc(Db, DocId, Params)","anchor":"open_doc/3"},{"id":"open_or_create_db/2","deprecated":false,"title":"open_or_create_db(Server, DbName)","anchor":"open_or_create_db/2"},{"id":"open_or_create_db/3","deprecated":false,"title":"open_or_create_db(Server, DbName, Options)","anchor":"open_or_create_db/3"},{"id":"open_or_create_db/4","deprecated":false,"title":"open_or_create_db(Server, DbName0, Options, Params)","anchor":"open_or_create_db/4"},{"id":"put_attachment/4","deprecated":false,"title":"put_attachment(Db, DocId, Name, Body)","anchor":"put_attachment/4"},{"id":"put_attachment/5","deprecated":false,"title":"put_attachment(Db, DocId, Name, Body, Options)","anchor":"put_attachment/5"},{"id":"replicate/2","deprecated":false,"title":"replicate(Server, RepObj)","anchor":"replicate/2"},{"id":"replicate/3","deprecated":false,"title":"replicate(Server, Source, Target)","anchor":"replicate/3"},{"id":"replicate/4","deprecated":false,"title":"replicate(Server, Source, Target, Options)","anchor":"replicate/4"},{"id":"save_doc/2","deprecated":false,"title":"save_doc(Db, Doc)","anchor":"save_doc/2"},{"id":"save_doc/3","deprecated":false,"title":"save_doc(Db, Doc, Options)","anchor":"save_doc/3"},{"id":"save_doc/4","deprecated":false,"title":"save_doc(Db, MapDoc, Atts, Options)","anchor":"save_doc/4"},{"id":"save_docs/2","deprecated":false,"title":"save_docs(Db, Docs)","anchor":"save_docs/2"},{"id":"save_docs/3","deprecated":false,"title":"save_docs(Db, Docs, Options)","anchor":"save_docs/3"},{"id":"send_attachment/2","deprecated":false,"title":"send_attachment(Ref, Msg)","anchor":"send_attachment/2"},{"id":"server_connection/0","deprecated":false,"title":"server_connection()","anchor":"server_connection/0"},{"id":"server_connection/1","deprecated":false,"title":"server_connection(URL)","anchor":"server_connection/1"},{"id":"server_connection/2","deprecated":false,"title":"server_connection(URL, Options0)","anchor":"server_connection/2"},{"id":"server_connection/4","deprecated":false,"title":"server_connection(Host, Port, Prefix, OptionsList)","anchor":"server_connection/4"},{"id":"server_info/1","deprecated":false,"title":"server_info(Server)","anchor":"server_info/1"},{"id":"stream_attachment/1","deprecated":false,"title":"stream_attachment(Ref)","anchor":"stream_attachment/1"},{"id":"stream_doc/1","deprecated":false,"title":"stream_doc(_)","anchor":"stream_doc/1"},{"id":"view_cleanup/1","deprecated":false,"title":"view_cleanup(Db)","anchor":"view_cleanup/1"}],"key":"functions"}]},{"id":"couchbeam_app","deprecated":false,"group":"","title":"couchbeam_app","sections":[],"nodeGroups":[{"name":"Functions","nodes":[{"id":"start/2","deprecated":false,"title":"start(Type, StartArgs)","anchor":"start/2"},{"id":"stop/1","deprecated":false,"title":"stop(State)","anchor":"stop/1"}],"key":"functions"}]},{"id":"couchbeam_attachments","deprecated":false,"group":"","title":"couchbeam_attachments","sections":[],"nodeGroups":[{"name":"Types","nodes":[{"id":"doc/0","deprecated":false,"title":"doc/0","anchor":"t:doc/0"},{"id":"ejson_object/0","deprecated":false,"title":"ejson_object/0","anchor":"t:ejson_object/0"}],"key":"types"},{"name":"Functions","nodes":[{"id":"add_inline/3","deprecated":false,"title":"add_inline(Doc, Content, AName)","anchor":"add_inline/3"},{"id":"add_inline/4","deprecated":false,"title":"add_inline(Doc, Content, AName, ContentType)","anchor":"add_inline/4"},{"id":"add_stub/3","deprecated":false,"title":"add_stub(Doc, Name, ContentType)","anchor":"add_stub/3"},{"id":"delete_inline/2","deprecated":false,"title":"delete_inline(Doc, AName)","anchor":"delete_inline/2"}],"key":"functions"}]},{"id":"couchbeam_changes","deprecated":false,"group":"","title":"couchbeam_changes","sections":[],"nodeGroups":[{"name":"Types","nodes":[{"id":"changes_option/0","deprecated":false,"title":"changes_option/0","anchor":"t:changes_option/0"},{"id":"changes_options/0","deprecated":false,"title":"changes_options/0","anchor":"t:changes_options/0"},{"id":"db/0","deprecated":false,"title":"db/0","anchor":"t:db/0"},{"id":"server/0","deprecated":false,"title":"server/0","anchor":"t:server/0"}],"key":"types"},{"name":"Functions","nodes":[{"id":"cancel_stream/1","deprecated":false,"title":"cancel_stream(Ref)","anchor":"cancel_stream/1"},{"id":"follow/1","deprecated":false,"title":"follow(Db)","anchor":"follow/1"},{"id":"follow/2","deprecated":false,"title":"follow(Db, Options)","anchor":"follow/2"},{"id":"follow_once/1","deprecated":false,"title":"follow_once(Db)","anchor":"follow_once/1"},{"id":"follow_once/2","deprecated":false,"title":"follow_once(Db, Options)","anchor":"follow_once/2"},{"id":"stream_next/1","deprecated":false,"title":"stream_next(Ref)","anchor":"stream_next/1"}],"key":"functions"}]},{"id":"couchbeam_changes_stream","deprecated":false,"group":"","title":"couchbeam_changes_stream","sections":[],"nodeGroups":[{"name":"Functions","nodes":[{"id":"init_stream/5","deprecated":false,"title":"init_stream(Parent, Owner, StreamRef, Db, Options)","anchor":"init_stream/5"},{"id":"maybe_continue/1","deprecated":false,"title":"maybe_continue(State)","anchor":"maybe_continue/1"},{"id":"start_link/4","deprecated":false,"title":"start_link(Owner, StreamRef, Db, Options)","anchor":"start_link/4"},{"id":"system_code_change/4","deprecated":false,"title":"system_code_change(Misc, _, _, _)","anchor":"system_code_change/4"},{"id":"system_continue/3","deprecated":false,"title":"system_continue(_, _, _)","anchor":"system_continue/3"},{"id":"system_terminate/4","deprecated":false,"title":"system_terminate(Reason, _, _, State)","anchor":"system_terminate/4"},{"id":"wait_reconnect/1","deprecated":false,"title":"wait_reconnect(State)","anchor":"wait_reconnect/1"}],"key":"functions"}]},{"id":"couchbeam_changes_sup","deprecated":false,"group":"","title":"couchbeam_changes_sup","sections":[],"nodeGroups":[{"name":"Functions","nodes":[{"id":"init/1","deprecated":false,"title":"init(_)","anchor":"init/1"},{"id":"start_link/0","deprecated":false,"title":"start_link()","anchor":"start_link/0"}],"key":"functions"}]},{"id":"couchbeam_doc","deprecated":false,"group":"","title":"couchbeam_doc","sections":[],"nodeGroups":[{"name":"Types","nodes":[{"id":"doc/0","deprecated":false,"title":"doc/0","anchor":"t:doc/0"},{"id":"ejson_array/0","deprecated":false,"title":"ejson_array/0","anchor":"t:ejson_array/0"},{"id":"ejson_number/0","deprecated":false,"title":"ejson_number/0","anchor":"t:ejson_number/0"},{"id":"ejson_object/0","deprecated":false,"title":"ejson_object/0","anchor":"t:ejson_object/0"},{"id":"ejson_string/0","deprecated":false,"title":"ejson_string/0","anchor":"t:ejson_string/0"},{"id":"ejson_term/0","deprecated":false,"title":"ejson_term/0","anchor":"t:ejson_term/0"}],"key":"types"},{"name":"Functions","nodes":[{"id":"delete_value/2","deprecated":false,"title":"delete_value(Key, JsonObj)","anchor":"delete_value/2"},{"id":"extend/2","deprecated":false,"title":"extend(R, JsonObj)","anchor":"extend/2"},{"id":"extend/3","deprecated":false,"title":"extend(Key, Value, JsonObj)","anchor":"extend/3"},{"id":"get_id/1","deprecated":false,"title":"get_id(Doc)","anchor":"get_id/1"},{"id":"get_idrev/1","deprecated":false,"title":"get_idrev(Doc)","anchor":"get_idrev/1"},{"id":"get_rev/1","deprecated":false,"title":"get_rev(Doc)","anchor":"get_rev/1"},{"id":"get_value/2","deprecated":false,"title":"get_value(Key, JsonObj)","anchor":"get_value/2"},{"id":"get_value/3","deprecated":false,"title":"get_value(Key, JsonObj, Default)","anchor":"get_value/3"},{"id":"is_saved/1","deprecated":false,"title":"is_saved(Doc)","anchor":"is_saved/1"},{"id":"set_value/3","deprecated":false,"title":"set_value(Key, Value, JsonObj)","anchor":"set_value/3"},{"id":"take_value/2","deprecated":false,"title":"take_value(Key, JsonObj)","anchor":"take_value/2"},{"id":"take_value/3","deprecated":false,"title":"take_value(Key, JsonObj, Default)","anchor":"take_value/3"}],"key":"functions"}]},{"id":"couchbeam_ejson","deprecated":false,"group":"","title":"couchbeam_ejson","sections":[],"nodeGroups":[{"name":"Types","nodes":[{"id":"ejson/0","deprecated":false,"title":"ejson/0","anchor":"t:ejson/0"},{"id":"ejson_array/0","deprecated":false,"title":"ejson_array/0","anchor":"t:ejson_array/0"},{"id":"ejson_number/0","deprecated":false,"title":"ejson_number/0","anchor":"t:ejson_number/0"},{"id":"ejson_object/0","deprecated":false,"title":"ejson_object/0","anchor":"t:ejson_object/0"},{"id":"ejson_string/0","deprecated":false,"title":"ejson_string/0","anchor":"t:ejson_string/0"},{"id":"ejson_term/0","deprecated":false,"title":"ejson_term/0","anchor":"t:ejson_term/0"}],"key":"types"},{"name":"Functions","nodes":[{"id":"decode/1","deprecated":false,"title":"decode(D)","anchor":"decode/1"},{"id":"encode/1","deprecated":false,"title":"encode(D)","anchor":"encode/1"},{"id":"post_decode/1","deprecated":false,"title":"post_decode(Term)","anchor":"post_decode/1"}],"key":"functions"}]},{"id":"couchbeam_httpc","deprecated":false,"group":"","title":"couchbeam_httpc","sections":[],"nodeGroups":[{"name":"Types","nodes":[{"id":"db/0","deprecated":false,"title":"db/0","anchor":"t:db/0"},{"id":"server/0","deprecated":false,"title":"server/0","anchor":"t:server/0"}],"key":"types"},{"name":"Functions","nodes":[{"id":"db_request/5","deprecated":false,"title":"db_request(Method, Url, Headers, Body, Options)","anchor":"db_request/5"},{"id":"db_request/6","deprecated":false,"title":"db_request(Method, Url, Headers, Body, Options, Expect)","anchor":"db_request/6"},{"id":"db_resp/2","deprecated":false,"title":"db_resp(Resp, Expect)","anchor":"db_resp/2"},{"id":"db_url/1","deprecated":false,"title":"db_url(Db)","anchor":"db_url/1"},{"id":"doc_url/2","deprecated":false,"title":"doc_url(Db, DocId)","anchor":"doc_url/2"},{"id":"json_body/1","deprecated":false,"title":"json_body(Ref)","anchor":"json_body/1"},{"id":"make_headers/4","deprecated":false,"title":"make_headers(Method, Url, Headers, Options)","anchor":"make_headers/4"},{"id":"maybe_oauth_header/4","deprecated":false,"title":"maybe_oauth_header(Method, Url, Headers, Options)","anchor":"maybe_oauth_header/4"},{"id":"request/5","deprecated":false,"title":"request(Method, Url, Headers, Body, Options)","anchor":"request/5"},{"id":"server_url/1","deprecated":false,"title":"server_url(Server)","anchor":"server_url/1"}],"key":"functions"}]},{"id":"couchbeam_sup","deprecated":false,"group":"","title":"couchbeam_sup","sections":[],"nodeGroups":[{"name":"Functions","nodes":[{"id":"init/1","deprecated":false,"title":"init(_)","anchor":"init/1"},{"id":"start_link/0","deprecated":false,"title":"start_link()","anchor":"start_link/0"}],"key":"functions"}]},{"id":"couchbeam_util","deprecated":false,"group":"","title":"couchbeam_util","sections":[],"nodeGroups":[{"name":"Functions","nodes":[{"id":"binary_env/2","deprecated":false,"title":"binary_env(Key, Default)","anchor":"binary_env/2"},{"id":"dbname/1","deprecated":false,"title":"dbname(DbName)","anchor":"dbname/1"},{"id":"deprecated/3","deprecated":false,"title":"deprecated(Old, New, When)","anchor":"deprecated/3"},{"id":"encode_att_name/1","deprecated":false,"title":"encode_att_name(Name)","anchor":"encode_att_name/1"},{"id":"encode_docid1/1","deprecated":false,"title":"encode_docid1(DocId)","anchor":"encode_docid1/1"},{"id":"encode_docid/1","deprecated":false,"title":"encode_docid(DocId)","anchor":"encode_docid/1"},{"id":"encode_docid_noop/1","deprecated":false,"title":"encode_docid_noop(DocId)","anchor":"encode_docid_noop/1"},{"id":"encode_query/1","deprecated":false,"title":"encode_query(QSL)","anchor":"encode_query/1"},{"id":"encode_query_value/2","deprecated":false,"title":"encode_query_value(K, V)","anchor":"encode_query_value/2"},{"id":"force_param/3","deprecated":false,"title":"force_param(Key, Value, Options)","anchor":"force_param/3"},{"id":"get_app_env/2","deprecated":false,"title":"get_app_env(Env, Default)","anchor":"get_app_env/2"},{"id":"get_value/2","deprecated":false,"title":"get_value(Key, Prop)","anchor":"get_value/2"},{"id":"get_value/3","deprecated":false,"title":"get_value(Key, Prop, Default)","anchor":"get_value/3"},{"id":"oauth_header/3","deprecated":false,"title":"oauth_header(Url, Action, OauthProps)","anchor":"oauth_header/3"},{"id":"parse_options/1","deprecated":false,"title":"parse_options(Options)","anchor":"parse_options/1"},{"id":"parse_options/2","deprecated":false,"title":"parse_options(Rest, Acc)","anchor":"parse_options/2"},{"id":"propmerge1/2","deprecated":false,"title":"propmerge1(L1, L2)","anchor":"propmerge1/2"},{"id":"propmerge/3","deprecated":false,"title":"propmerge(F, L1, L2)","anchor":"propmerge/3"},{"id":"proxy_header/3","deprecated":false,"title":"proxy_header(UserName, Roles, Secret)","anchor":"proxy_header/3"},{"id":"proxy_token/2","deprecated":false,"title":"proxy_token(Secret, UserName)","anchor":"proxy_token/2"},{"id":"shutdown_sync/1","deprecated":false,"title":"shutdown_sync(Pid)","anchor":"shutdown_sync/1"},{"id":"start_app_deps/1","deprecated":false,"title":"start_app_deps(App)","anchor":"start_app_deps/1"},{"id":"to_atom/1","deprecated":false,"title":"to_atom(V)","anchor":"to_atom/1"},{"id":"to_binary/1","deprecated":false,"title":"to_binary(V)","anchor":"to_binary/1"},{"id":"to_integer/1","deprecated":false,"title":"to_integer(V)","anchor":"to_integer/1"},{"id":"to_list/1","deprecated":false,"title":"to_list(V)","anchor":"to_list/1"}],"key":"functions"}]},{"id":"couchbeam_uuids","deprecated":false,"group":"","title":"couchbeam_uuids","sections":[],"nodeGroups":[{"name":"Types","nodes":[{"id":"server/0","deprecated":false,"title":"server/0","anchor":"t:server/0"}],"key":"types"},{"name":"Functions","nodes":[{"id":"code_change/3","deprecated":false,"title":"code_change(OldVsn, State, Extra)","anchor":"code_change/3"},{"id":"get_uuids/2","deprecated":false,"title":"get_uuids(Server, Count)","anchor":"get_uuids/2"},{"id":"handle_call/3","deprecated":false,"title":"handle_call(_, From, State)","anchor":"handle_call/3"},{"id":"handle_cast/2","deprecated":false,"title":"handle_cast(Msg, State)","anchor":"handle_cast/2"},{"id":"handle_info/2","deprecated":false,"title":"handle_info(Info, State)","anchor":"handle_info/2"},{"id":"init/1","deprecated":false,"title":"init(_)","anchor":"init/1"},{"id":"random/0","deprecated":false,"title":"random()","anchor":"random/0"},{"id":"start_link/0","deprecated":false,"title":"start_link()","anchor":"start_link/0"},{"id":"terminate/2","deprecated":false,"title":"terminate(Reason, State)","anchor":"terminate/2"},{"id":"utc_random/0","deprecated":false,"title":"utc_random()","anchor":"utc_random/0"}],"key":"functions"}]},{"id":"couchbeam_view","deprecated":false,"group":"","title":"couchbeam_view","sections":[],"nodeGroups":[{"name":"Types","nodes":[{"id":"db/0","deprecated":false,"title":"db/0","anchor":"t:db/0"},{"id":"design_name/0","deprecated":false,"title":"design_name/0","anchor":"t:design_name/0"},{"id":"ejson_object/0","deprecated":false,"title":"ejson_object/0","anchor":"t:ejson_object/0"},{"id":"server/0","deprecated":false,"title":"server/0","anchor":"t:server/0"},{"id":"show_option/0","deprecated":false,"title":"show_option/0","anchor":"t:show_option/0"},{"id":"show_options/0","deprecated":false,"title":"show_options/0","anchor":"t:show_options/0"},{"id":"stale/0","deprecated":false,"title":"stale/0","anchor":"t:stale/0"},{"id":"view_name/0","deprecated":false,"title":"view_name/0","anchor":"t:view_name/0"},{"id":"view_option/0","deprecated":false,"title":"view_option/0","anchor":"t:view_option/0"},{"id":"view_options/0","deprecated":false,"title":"view_options/0","anchor":"t:view_options/0"},{"id":"view_query_args/0","deprecated":false,"title":"view_query_args/0","anchor":"t:view_query_args/0"}],"key":"types"},{"name":"Functions","nodes":[{"id":"all/1","deprecated":false,"title":"all(Db)","anchor":"all/1"},{"id":"all/2","deprecated":false,"title":"all(Db, Options)","anchor":"all/2"},{"id":"cancel_stream/1","deprecated":false,"title":"cancel_stream(Ref)","anchor":"cancel_stream/1"},{"id":"count/1","deprecated":false,"title":"count(Db)","anchor":"count/1"},{"id":"count/2","deprecated":false,"title":"count(Db, ViewName)","anchor":"count/2"},{"id":"count/3","deprecated":false,"title":"count(Db, ViewName, Options)","anchor":"count/3"},{"id":"fetch/1","deprecated":false,"title":"fetch(Db)","anchor":"fetch/1"},{"id":"fetch/2","deprecated":false,"title":"fetch(Db, ViewName)","anchor":"fetch/2"},{"id":"fetch/3","deprecated":false,"title":"fetch(Db, ViewName, Options)","anchor":"fetch/3"},{"id":"first/1","deprecated":false,"title":"first(Db)","anchor":"first/1"},{"id":"first/2","deprecated":false,"title":"first(Db, ViewName)","anchor":"first/2"},{"id":"first/3","deprecated":false,"title":"first(Db, ViewName, Options)","anchor":"first/3"},{"id":"fold/4","deprecated":false,"title":"fold(Function, Acc, Db, ViewName)","anchor":"fold/4"},{"id":"fold/5","deprecated":false,"title":"fold(Function, Acc, Db, ViewName, Options)","anchor":"fold/5"},{"id":"foreach/3","deprecated":false,"title":"foreach(Function, Db, ViewName)","anchor":"foreach/3"},{"id":"foreach/4","deprecated":false,"title":"foreach(Function, Db, ViewName, Options)","anchor":"foreach/4"},{"id":"parse_view_options/1","deprecated":false,"title":"parse_view_options(Options)","anchor":"parse_view_options/1"},{"id":"show/2","deprecated":false,"title":"show(Db, ShowName)","anchor":"show/2"},{"id":"show/3","deprecated":false,"title":"show(Db, ShowName, DocId)","anchor":"show/3"},{"id":"show/4","deprecated":false,"title":"show(Db, _, DocId, Options)","anchor":"show/4"},{"id":"stream/2","deprecated":false,"title":"stream(Db, ViewName)","anchor":"stream/2"},{"id":"stream/3","deprecated":false,"title":"stream(Db, ViewName, Options)","anchor":"stream/3"},{"id":"stream_next/1","deprecated":false,"title":"stream_next(Ref)","anchor":"stream_next/1"}],"key":"functions"}]},{"id":"couchbeam_view_stream","deprecated":false,"group":"","title":"couchbeam_view_stream","sections":[],"nodeGroups":[{"name":"Functions","nodes":[{"id":"init_stream/5","deprecated":false,"title":"init_stream(Parent, Owner, StreamRef, Req, StreamOptions)","anchor":"init_stream/5"},{"id":"maybe_continue/1","deprecated":false,"title":"maybe_continue(State)","anchor":"maybe_continue/1"},{"id":"start_link/4","deprecated":false,"title":"start_link(Owner, StreamRef, _, StreamOptions)","anchor":"start_link/4"},{"id":"system_code_change/4","deprecated":false,"title":"system_code_change(Misc, _, _, _)","anchor":"system_code_change/4"},{"id":"system_continue/3","deprecated":false,"title":"system_continue(_, _, _)","anchor":"system_continue/3"},{"id":"system_terminate/4","deprecated":false,"title":"system_terminate(Reason, _, _, State)","anchor":"system_terminate/4"}],"key":"functions"}]},{"id":"couchbeam_view_sup","deprecated":false,"group":"","title":"couchbeam_view_sup","sections":[],"nodeGroups":[{"name":"Functions","nodes":[{"id":"init/1","deprecated":false,"title":"init(_)","anchor":"init/1"},{"id":"start_link/0","deprecated":false,"title":"start_link()","anchor":"start_link/0"}],"key":"functions"}]},{"id":"gen_changes","deprecated":false,"group":"","title":"gen_changes","sections":[],"nodeGroups":[{"name":"Functions","nodes":[{"id":"behaviour_info/1","deprecated":false,"title":"behaviour_info(_)","anchor":"behaviour_info/1"},{"id":"call/2","deprecated":false,"title":"call(Name, Request)","anchor":"call/2"},{"id":"call/3","deprecated":false,"title":"call(Name, Request, Timeout)","anchor":"call/3"},{"id":"cast/2","deprecated":false,"title":"cast(Dest, Request)","anchor":"cast/2"},{"id":"code_change/3","deprecated":false,"title":"code_change(OldVersion, State, Extra)","anchor":"code_change/3"},{"id":"get_seq/1","deprecated":false,"title":"get_seq(Pid)","anchor":"get_seq/1"},{"id":"handle_call/3","deprecated":false,"title":"handle_call(Request, From, State)","anchor":"handle_call/3"},{"id":"handle_cast/2","deprecated":false,"title":"handle_cast(Msg, State)","anchor":"handle_cast/2"},{"id":"handle_info/2","deprecated":false,"title":"handle_info(Info, State)","anchor":"handle_info/2"},{"id":"init/1","deprecated":false,"title":"init(_)","anchor":"init/1"},{"id":"start_link/4","deprecated":false,"title":"start_link(Module, Db, Options, InitArgs)","anchor":"start_link/4"},{"id":"stop/1","deprecated":false,"title":"stop(Pid)","anchor":"stop/1"},{"id":"terminate/2","deprecated":false,"title":"terminate(Reason, Gen_changes_state)","anchor":"terminate/2"}],"key":"functions"}]},{"id":"json_stream_parse","deprecated":false,"group":"","title":"json_stream_parse","sections":[],"nodeGroups":[{"name":"Functions","nodes":[{"id":"feed/2","deprecated":false,"title":"feed(Data, St)","anchor":"feed/2"},{"id":"finish/1","deprecated":false,"title":"finish(S)","anchor":"finish/1"},{"id":"init/0","deprecated":false,"title":"init()","anchor":"init/0"}],"key":"functions"}]}],"extras":[{"id":"api-reference","group":"","title":"API Reference","headers":[{"id":"Modules","anchor":"modules"}]},{"id":"readme","group":"","title":"Readme","headers":[{"id":"Installation","anchor":"installation"},{"id":"Basic Usage","anchor":"basic-usage"},{"id":"Contribute","anchor":"contribute"}]},{"id":"news","group":"","title":"Changelog","headers":[{"id":"couchbeam NEWS","anchor":"couchbeam-news"},{"id":"version 2.0.0 / 2025-09-03","anchor":"version-2-0-0-2025-09-03"},{"id":"version 1.7.1 / 2025-07-24","anchor":"version-1-7-1-2025-07-24"},{"id":"version 1.7.0 / 2025-05-28","anchor":"version-1-7-0-2025-05-28"},{"id":"version 1.6.0 / 2025-01-26","anchor":"version-1-6-0-2025-01-26"},{"id":"version 1.5.4 / 2025-02-20","anchor":"version-1-5-4-2025-02-20"},{"id":"version 1.5.3 / 2024-08-20","anchor":"version-1-5-3-2024-08-20"},{"id":"version 1.5.1 / 2024-11-07","anchor":"version-1-5-1-2024-11-07"},{"id":"version 1.5.1 / 2024-11-07","anchor":"version-1-5-1-2024-11-07-1"},{"id":"version 1.5.0 / 2023-10-11","anchor":"version-1-5-0-2023-10-11"},{"id":"version 1.4.1 / 2016-09-26","anchor":"version-1-4-1-2016-09-26"},{"id":"version 1.4.0 / 2016-09-22","anchor":"version-1-4-0-2016-09-22"},{"id":"version 1.3.1 / 2016-07-01","anchor":"version-1-3-1-2016-07-01"},{"id":"version 1.3.0 / 2016-03-22","anchor":"version-1-3-0-2016-03-22"},{"id":"version 1.2.1 / 2015/11/04","anchor":"version-1-2-1-2015-11-04"},{"id":"version 1.2.0 / 2015/11/04","anchor":"version-1-2-0-2015-11-04"},{"id":"version 1.1.8 / 2015-08-27","anchor":"version-1-1-8-2015-08-27"},{"id":"version 1.1.7 / 2015-03-11","anchor":"version-1-1-7-2015-03-11"},{"id":"version 1.1.6 / 2015-01-02","anchor":"version-1-1-6-2015-01-02"},{"id":"version 1.1.5 / 2014-12-09","anchor":"version-1-1-5-2014-12-09"},{"id":"version 1.1.4 / 2014-12-01","anchor":"version-1-1-4-2014-12-01"},{"id":"version 1.1.3 / 2014-11-30","anchor":"version-1-1-3-2014-11-30"},{"id":"version 1.1.2 / 2014-11-15","anchor":"version-1-1-2-2014-11-15"},{"id":"version 1.1.1 / 2014-11-11","anchor":"version-1-1-1-2014-11-11"},{"id":"version 1.1.0 / 2014-10-28","anchor":"version-1-1-0-2014-10-28"},{"id":"version 1.0.7 / 2014-07-08","anchor":"version-1-0-7-2014-07-08"},{"id":"version 1.0.6 / 2014-04-18","anchor":"version-1-0-6-2014-04-18"},{"id":"version 1.0.5 / 2014-04-18","anchor":"version-1-0-5-2014-04-18"},{"id":"version 1.0.4 / 2014-04-15","anchor":"version-1-0-4-2014-04-15"},{"id":"version 1.0.3 / 2014-04-15","anchor":"version-1-0-3-2014-04-15"},{"id":"version 1.0.2 / 2014-01-03","anchor":"version-1-0-2-2014-01-03"},{"id":"version 1.0.1 / 2013-12-30","anchor":"version-1-0-1-2013-12-30"},{"id":"version 1.0.0 / 2013-12-21","anchor":"version-1-0-0-2013-12-21"},{"id":"version 0.10.0 / 2013-12-21","anchor":"version-0-10-0-2013-12-21"},{"id":"version 0.9.3 / 2013-12-07","anchor":"version-0-9-3-2013-12-07"},{"id":"version 0.9.2 / 2013-12-07","anchor":"version-0-9-2-2013-12-07"},{"id":"version 0.9.1 / 2013-12-05","anchor":"version-0-9-1-2013-12-05"},{"id":"version 0.9.0 / 2013-12-05","anchor":"version-0-9-0-2013-12-05"},{"id":"version 0.7.0 / 2011-07-05","anchor":"version-0-7-0-2011-07-05"}]},{"id":"notice","group":"","title":"Notice","headers":[]},{"id":"license","group":"","title":"License","headers":[]}],"tasks":[]} \ No newline at end of file diff --git a/site/gen_changes.html b/site/gen_changes.html new file mode 100644 index 00000000..80e87e9a --- /dev/null +++ b/site/gen_changes.html @@ -0,0 +1,554 @@ + + + + + + + + + + + gen_changes — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + +
+
+

+ gen_changes behaviour + (couchbeam v2.0.0) + +

+ + + + View Source + + +
+ + +
+

gen_changes CouchDB continuous changes consumer behavior This behaviour allows you to create easily a server that consume Couchdb continuous changes

+
+ +
+ +
+

+ + + + Summary +

+
+

+ Functions +

+ +
+ + +
+ +
+ + +
+ + + +
+ + +
+ + + +
+
+ get_seq(Pid) + +
+ +
+ + + + + + + +
+
+ init(_) + +
+ +
+ +
+ + +

create a gen_changes process as part of a supervision tree. The function should be called, directly or indirectly, by the supervisor. InitArgs::list()) -> term() changesoptions() = [changeoption()] changeoption() = {include_docs, string()} | {filter, string()} | {since, integer()|string()} | {heartbeat, string()|boolean()}

+ +
+ +
+
+ stop(Pid) + +
+ +
+ + + +
+ +
+ + +
+

+ + + + Functions +

+
+
+ +
+ + + +
+

behaviour_info(_)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

call(Name, Request)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

call(Name, Request, Timeout)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

cast(Dest, Request)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

code_change(OldVersion, State, Extra)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

get_seq(Pid)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

handle_call(Request, From, State)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

handle_cast(Msg, State)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

handle_info(Info, State)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

init(_)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

start_link(Module, Db, Options, InitArgs)

+ + + + + + +
+
+ +
+ +

create a gen_changes process as part of a supervision tree. The function should be called, directly or indirectly, by the supervisor. InitArgs::list()) -> term() changesoptions() = [changeoption()] changeoption() = {include_docs, string()} | {filter, string()} | {since, integer()|string()} | {heartbeat, string()|boolean()}

+
+
+
+ +
+ + + +
+

stop(Pid)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

terminate(Reason, Gen_changes_state)

+ + + + + + +
+
+ +
+ + +
+
+ +
+
+ + +
+
+
+ + + diff --git a/site/index.html b/site/index.html new file mode 100644 index 00000000..6ad5c4bb --- /dev/null +++ b/site/index.html @@ -0,0 +1,10 @@ + + + + + couchbeam v2.0.0 — Documentation + + + + + diff --git a/site/json_stream_parse.html b/site/json_stream_parse.html new file mode 100644 index 00000000..c08505d4 --- /dev/null +++ b/site/json_stream_parse.html @@ -0,0 +1,248 @@ + + + + + + + + + + + json_stream_parse — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + +
+
+

+ json_stream_parse + (couchbeam v2.0.0) + +

+ + + + View Source + + +
+ + +
+ +
+

+ + + + Summary +

+
+

+ Functions +

+ +
+ + +
+ +
+
+ finish(S) + +
+ +
+ +
+
+ init() + +
+ +
+ +
+ +
+ + +
+

+ + + + Functions +

+
+
+ +
+ + + +
+

feed(Data, St)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

finish(S)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

init()

+ + + + + + +
+
+ +
+ + +
+
+ +
+
+ + +
+
+
+ + + diff --git a/site/license.html b/site/license.html new file mode 100644 index 00000000..9deed1dc --- /dev/null +++ b/site/license.html @@ -0,0 +1,170 @@ + + + + + + + + + + + License — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + +
+
+

License

+ + + + + View Source + + +
+ + +
+2009-2025 (c) Benoit Chesneau
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+ +
+ + + +
+
+
+ + + diff --git a/site/news.html b/site/news.html new file mode 100644 index 00000000..72b49db8 --- /dev/null +++ b/site/news.html @@ -0,0 +1,192 @@ + + + + + + + + + + + Changelog — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + +
+
+

Changelog

+ + + + + View Source + + +
+ + +

couchbeam NEWS

version 2.0.0 / 2025-09-03

  • move from propos lists to maps for json
  • remove JSX & Jiffy Usage for erlang/0TP 28.0+ json module
  • View and changes streaming now use a simpler parser

BREAKING CHANGE

  • move to maps, you will need to migrate your application to use them. +no backward compatibility is provided

version 1.7.1 / 2025-07-24

  • update hackney depdendency to 1.25.0

version 1.7.0 / 2025-05-28

  • fix resource leaks and race conditions in stream modules
  • fix unclosed hackney connections on error paths
  • add proper cleanup for monitor references using try-finally
  • fix ETS table race conditions by checking process liveness
  • improve stream initialization order to prevent races
  • add error handling for hackney operations to prevent leaks
  • fix changes stream registration race condition by registering before parent notification

version 1.6.0 / 2025-01-26

  • add support for CouchDB _find endpoint
  • add ability to query _show functions
  • add option for disabling view_stream usage (enabled by default)
  • fix error handling in gen_changes callback handling
  • fix resource cleanup in stream modules to prevent connection leaks
  • improve replication test reliability and timeout handling
  • update hackney dependency to 1.23
  • update jsx dependency
  • add GitHub Actions for CouchDB testing
  • fix dialyzer complaints and pattern matching issues
  • OTP 27 compatibility improvements

version 1.5.4 / 2025-02-20

  • bump hackney 1.22.0

version 1.5.3 / 2024-08-20

  • fix packaging

version 1.5.1 / 2024-11-07

  • fix pattern matching

version 1.5.1 / 2024-11-07

  • fix: handle condition that may cause persistent CLOSE-WAIT sockets

version 1.5.0 / 2023-10-11

  • use hackney 1.20.0
  • fix compatibility with couchdb 3
  • fix compatibility with Erlang >= 23

version 1.4.1 / 2016-09-26

  • maintainance update

version 1.4.0 / 2016-09-22

  • maintainance update.

version 1.3.1 / 2016-07-01

  • fix: accept 202 status in couchbeam:save_doc/4 function (#144)
  • fix: spec syntax to build with Erlang 19 (#145)

version 1.3.0 / 2016-03-22

version 1.2.1 / 2015/11/04

  • also support hackney 1.4.4 for rebar2.
  • fix hex.pm release to really use 1.4.4

version 1.2.0 / 2015/11/04

  • move to eunit for tests.
  • hex.pm support
  • mix & rebar3 build tools support
  • bump hackney to 1.4.4
  • bump jsx to 2.2.8

Breaking change

erlang-oauth is now optionnal and won't be installed by default.

version 1.1.8 / 2015-08-27

  • use latest stable branch of hackney

version 1.1.7 / 2015-03-11

  • bump hackney to 1.1.0
  • fix Conten-Type header ehen posting doc IDS in changes #126
  • fix documentation

version 1.1.6 / 2015-01-02

  • fix included_applications (#122)

version 1.1.5 / 2014-12-09

  • improvement: do not force connections options to nodelay
  • update to Hackney 1.0.4 fix #120
  • fix: retry fecthing UUIDS on error (#121)

version 1.1.4 / 2014-12-01

  • update to Hackney 1.0.1: more SSL +certificate authority handling.
  • fix: changes stream

version 1.1.3 / 2014-11-30

version 1.1.2 / 2014-11-15

  • remove spurious prints

version 1.1.1 / 2014-11-11

version 1.1.0 / 2014-10-28

  • update to hackney 0.14.3
  • fix memory leaks
  • correctly close sockets
  • fix streaming issue: don't wait the stream timeout to report the initial +error.
  • update JSX dependency to version 2.1.1

version 1.0.7 / 2014-07-08

version 1.0.6 / 2014-04-18

version 1.0.5 / 2014-04-18

  • improve connections with HTTP proxies
  • improve content-types detection of attachments
  • improve URL encoding normalzation, useful when connecting to an +international domain/URI
  • URL resolving is faster
  • bump to hackney 0.12.0

version 1.0.4 / 2014-04-15

  • remove spurious print

version 1.0.3 / 2014-04-15

  • add support for the new_edits option in bulk doc API.
  • improvement: send a doc as multipart that already contains attachments
  • bump hackney to 0.11.2
  • fix path encoding

version 1.0.2 / 2014-01-03

  • fix: send a doc as multipart that already contains attachments

version 1.0.1 / 2013-12-30

  • fix connection reusing in changes and view streams
  • bump hackney version to 0.10.1

version 1.0.0 / 2013-12-21

First stable release. This is a supported release.

  • send a doc and its attachments efficiently using the multipart +API.
  • add couchbeam:get_config/{1,2,3}, couchbeam:set_config/{4,5} and +couchbeam:delete_config/{3,4} to use the config +API.
  • add couchbeam_uuids:random/0 and couchbeam_uuids:utc_random/0 to +generate UUIDS in your app instead of reusing the UUID generated on +the node. By default couchbeam is fetching from the node, which is
  • add {error, forbidden} and {error, unauthenticated} as possible +results of a reply. +better if you want to use UUID based on the node time.
  • fix accept header handling

version 0.10.0 / 2013-12-21

  • add couchbeam:copy_doc/{2,3} to support the COPY API
  • add couchbeam:get_missing_revs/2 to get the list of missing +revisions
  • add support of the multipart +API when fetching a doc: This change make +couchbeam:open_doc/3 returns a multipart response {ok, {multipart, Stream}} +when using the attachments=true option. A new option {accept, <<"multipart/mixed">>} +can also be used with the options open_revs or revs to fetch the response as a multipart.
  • bump the hackney version to +0.9.1 .

With this change you can now efficiently retrieve a doc with all of its +attachments or a doc wit all its revisions. + master

version 0.9.3 / 2013-12-07

  • fix: couchbeam:open_or_create_db/2

version 0.9.2 / 2013-12-07

  • bump hackney version to 0.8.3

version 0.9.1 / 2013-12-05

  • fix design docid encoding

version 0.9.0 / 2013-12-05

This is a major release pre-1.0. API is now frozen and won't change much +until the version 1.0.

  • replaced the use of ibrowse by hackney to handle HTTP connections
  • new streaming +API in view
  • breaking change: remobe
  • breaking change: remove deprecated view API. Everything is now managed in the +couch_view module.
  • replace 'couchbeam_changes:stream' and 'couchbeam_changes:fetch' +functions by 'couchbeam_changes/follow' and 'couchbeam_changes:follow_once'.
  • breaking change: new attachment API
  • new: JSX a pure erlang JSON encoder/decoder is now the default. Jiffy +can be set at the compilation by defining 'WITH_JIFFY' in the Erlang +options.
  • removed mochiweb dependency.

version 0.7.0 / 2011-07-05

This release contains backwards incompatible changes.

  • New and more efficient couchbeam_changes API, we now parse json stream +instead of the try catch steps we used before.
  • New and more efficient couchbeam_view API. we now parse json stream +instead of getting all results. New couchbeam_view:stream and +couchbeam_view fetch functions have been added. We also don't use any +more a view record in other functions
  • HTTP functions have been moved to couchbeam_httpc modules
  • gen_changes behaviour has been updated to use the couchbeam_changes +API. It's also abble to restart a lost connection for longpoll and +continuous feeds.

Breaking Changes:

  • couchbeam:view and couchbeam:all_docs have been deprecated. Old views +functions using the #view{} record from these functions have been +moved in couchbeam_oldview module.
  • couchbeam:wait_changes, couchbeam:wait_changes_once, couchbeam:changes +functions have been deprecated and are now replaced by +couchbeam_changes:stream and couchbeam_changes:fetch functions.
+ +
+ + + +
+
+
+ + + diff --git a/site/notice.html b/site/notice.html new file mode 100644 index 00000000..d14e6b81 --- /dev/null +++ b/site/notice.html @@ -0,0 +1,164 @@ + + + + + + + + + + + Notice — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + +
+
+

Notice

+ + + + + View Source + + +
+ + +
+Couchbeam
+---------
+
+2009-2025 (c) Benoit Chesneau
+
+couchbeam is released under the MIT license. See the LICENSE file for the
+complete license.
+
+ +
+ + + +
+
+
+ + + diff --git a/site/readme.html b/site/readme.html new file mode 100644 index 00000000..31be4f41 --- /dev/null +++ b/site/readme.html @@ -0,0 +1,294 @@ + + + + + + + + + + + Readme — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + +
+
+

Couchbeam - simple Apache CouchDB client library for Erlang applications

+ + + + + View Source + + +
+ + +

Copyright (c) 2009-2025 Benoit Chesneau.

Version: 1.7.1

couchbeam

Couchbeam is a simple erlang library for Barrel or Apache CouchDB. Couchbeam provides you a full featured and easy client to access and manage multiple nodes.

Main features:

  • Complete support of the BarrelDB and Apache CouchDB API
  • Stream view results to your app
  • Stream changes feeds
  • reduced memory usage
  • fetch and send attachments in a streaming fashion
  • JSON encoding/decoding via Erlang/OTP stdlib json with maps

Useful modules are:

  • couchbeam: The couchbeam module is the main interface for interaction with this application. It includes functions for managing connections to Apache CouchDB or RCOUCH servers and databases and for performing document creations, updates, deletes, views...
  • couchbeam_doc Module to manipulate Documents structures. You can set values, +updates keys, ...
  • couchbeam_attachments: Module to manipulate attachments. You can add, remove +attachments in a Document structure (inline attachments).
  • couchbeam_view: Module to manage view results.
  • couchbeam_changes: Module to manage changes feeds. Follow continuously +the changes in a db or get all changes at once.

The goal of Couchbeam is to ease the access to the Apache CouchDB and RCOUCH HTTP API in erlang.

Read the NEWS file +to get last changelog.

Installation

Download the sources from our Github repository

To build the application simply run 'make'. This should build .beam, .app +files and documentation.

To run tests run 'make test'. +To generate doc, run 'make doc'.

Or add it to your rebar config

   erlang
+{deps, [
+    ....
+    {couchbeam, ".*", {git, "git://github.com/benoitc/couchbeam.git", {branch, "master"}}}
+]}.

Note to compile with jiffy you need to define in the erlang options the +variable WITH_JIFFY.

if you use rebar, add to your rebar.config:

   erlang
+{erl_opts, [{d, 'WITH_JIFFY'}]}.

or use the rebar command with the -D options:

   sh
+rebar compile -DWITH_JIFFY

Basic Usage

Start couchbeam

Couchbeam is an OTP +application. You have to start it first before using any of the +functions. The couchbeam application will start the default socket pool +for you.

To start in the console run:

   sh
+$ erl -pa ebin
+1> couchbeam:start().
+ok

It will start hackney and all of the application it depends on:

   erlang
+application:start(crypto),
+application:start(asn1),
+application:start(public_key),
+application:start(ssl),
+application:start(hackney),
+application:start(couchbeam).

Or add couchbeam to the applications property of your .app in a release

Create a connection to the server

To create a connection to a server machine:

   erlang
+Url = "http://localhost:5984",
+Options = [],
+S = couchbeam:server_connection(Url, Options).

Test the connection with couchbeam:server_info/1 :

   erlang
+{ok, _Version} = couchbeam:server_info(S).

Open or Create a database

All document operations are done in databases. To open a database simply do:

   erlang
+Options = [],
+{ok, Db} = couchbeam:open_db(Server, "testdb", Options).

To create a new one:

   erlang
+Options = [],
+{ok, Db} = couchbeam:create_db(Server, "testdb", Options).

You can also use the shorcut couchbeam:open_or_create_db/3. that +will create a database if it does not exist.

Make a new document

Make a new document:

   erlang
+Doc = #{
+    <<"_id">> => <<"test">>,
+    <<"content">> => <<"some text">>
+}.

And save it to the database:

   erlang
+{ok, Doc1} = couchbeam:save_doc(Db, Doc).

The couchbeam:save_doc/2 return a new document with updated +revision and if you do not specify the _id, a unique document id.

To change an document property use functions from couchbeam_doc.

Retrieve a document

To retrieve a document do:

   erlang
+{ok, Doc2} = couchbeam:open_doc(Db, "test").

If you want a specific revision:

   erlang
+Rev = couchbeam_doc:get_rev(Doc1),
+Options = [{rev, Rev}],
+{ok, Doc3} = couchbeam:open_doc(Db, "test", Options).

Here we get the revision from the document we previously stored. Any +options from the Apache CouchDB and RCOUCH API can be used.

Get all documents

To get all documents you have first to create an object +that will keep all informations.

   erlang
+Options = [include_docs],
+{ok, AllDocs} = couchbeam_view:all(Db, Options).

Example result (abridged):

   erlang
+{ok, [
+    #{
+      <<"id">> => <<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>,
+      <<"key">> => <<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>,
+      <<"value">> => #{<<"rev">> => <<"15-15c0b3c4efa74f9a80d28ac040f18bdb">>},
+      <<"doc">> => #{
+        <<"_id">> => <<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>,
+        <<"_rev">> => <<"15-15c0b3c4efa74f9a80d28ac040f18"...>>
+      }
+    }
+]}.

All functions to manipulate these results are in the couchbeam_view module.

Couch DB views

Views are workin like all_docs. You have to create a View object before +doing anything.

   erlang
+Options = [],
+DesignName = "designname",
+ViewName = "viewname",
+{ok, ViewResults} = couchbeam_view:fetch(Db, {DesignName, ViewName}, Options).

Like the all_docs function, use the functions +from couchbeam_view module to manipulate results. You can pass +any querying options from the view API.

Design doc are created like any documents:

   erlang
+DesignDoc = #{
+    <<"_id">> => <<"_design/couchbeam">>,
+    <<"language">> => <<"javascript">>,
+    <<"views">> => #{
+        <<"test">> => #{
+            <<"map">> => <<"function (doc) {\n if (doc.type == \"test\") {\n emit(doc._id, doc);\n}\n}">>
+        },
+        <<"test2">> => #{
+            <<"map">> => <<"function (doc) {\n if (doc.type == \"test2\") {\n emit(doc._id, null);\n}\n}">>
+        }
+    }
+},
+{ok, DesignDoc1} = couchbeam:save_doc(Db, DesignDoc).

You can also use couchapp to manage them +more easily.

Stream View results

While you can get results using couchbeam_views:fetch/2, you can also retrieve +all rows in a streaming fashion:

   erlang
+ViewFun = fun(Ref, F) ->
+    receive
+        {Ref, done} ->
+            io:format("done", []),
+            done;
+        {Ref, {row, Row}} ->
+            io:format("got ~p~n", [Row]),
+            F(Ref, F);
+        {error, Ref, Error} ->
+            io:format("error: ~p~n", [Error])
+    end
+end,
+
+{ok, StreamRef} = couchbeam_view:stream(Db, 'all_docs'),
+ViewFun(StreamRef, ViewFun),
+{ok, StreamRef2} = couchbeam_view:stream(Db, 'all_docs', [include_docs]),
+ViewFun(StreamRef2, ViewFun).

You can of course do the same with a view:

   erlang
+DesignNam = "designname",
+ViewName = "viewname",
+{ok, StreamRef3} = couchbeam_view:stream(Db, {DesignNam, ViewName}, [include_docs]),
+ViewFun(StreamRef3, ViewFun).

Put, Fetch and Delete documents attachments

You can add attachments to any documents. Attachments could be anything.

To send an attachment:

   erlang
+DocID = "test",
+AttName = "test.txt",
+Att = "some content I want to attach",
+Options = []
+{ok, _Result} = couchbeam:put_attachment(Db, DocId, AttName, Att, Options).

All attachments are streamed to servers. Att could be also be an iolist +or functions, see couchbeam:put_attachment/5 for more information.

To fetch an attachment:

   erlang
+{ok Att1} = couchbeam:fetch_attachment(Db, DocId, AttName).

You can use couchbeam:stream_attachment/1 for the stream +fetch.

To delete an attachment:

   erlang
+{ok, Doc4} = couchbeam:open_doc(Db, DocID),
+ok = couchbeam:delete_attachment(Db, Doc4, AttName).

Changes

Apache CouchDB and RCOUCH provide a means to get a list of changes made to documents in +the database. With couchbeam you can get changes using couchbeam_changes:follow_once/2. +This function returns all changes immediately. But you can also retrieve +all changes rows using longpolling :

   erlang
+Options = [],
+{ok, LastSeq, Rows} = couchbeam_changes:follow_once(Db, Options).

Options can be any Changes query parameters. See the change API for more informations.

You can also get continuous:

   erlang
+ChangesFun = fun(StreamRef, F) ->
+    receive
+        {StreamRef, {done, LastSeq}} ->
+            io:format("stopped, last seq is ~p~n", [LastSeq]),
+            ok;
+        {StreamRef, {change, Change}} ->
+            io:format("change row ~p ~n", [Change]),
+            F(StreamRef, F);
+        {StreamRef, Error}->
+            io:format("error ? ~p ~n,", [Error])
+    end
+end,
+Options = [continuous, heartbeat],
+{ok, StreamRef} = couchbeam_changes:follow(Db, Options),
+ChangesFun(StreamRef, ChangesFun).

Note: a gen_changes behaviour exists in couchbeam that you can +use to create your own specific gen_server receiving changes. Have a +look in the +example +for more info.

Authentication/ Connections options

You can authenticate to the database or Apache CouchDB or RCOUCH server by filling +options to the Option list in couchbeam:server_connection/4 for the +server or in couchbeam:create_db/3, couchbeam:open_db/3, +couchbeam:open_or_create_db/3 functions.

To set basic_auth on a server:

   erlang
+UserName = "guest",
+Password = "test",
+Url = "http://localhost:5984",
+Options = [{basic_auth, {UserName, Password}}],
+S1 = couchbeam:server_connection(Url, Options).

Couchbeam support SSL, OAuth, Basic Authentication, and Proxy. You can +also set a cookie. For more informations about the options have a look +in the couchbeam:server_connection/2 documentation.

Contribute

For issues, comments or feedback please create an +issue.

+ +
+ + + +
+
+
+ + + diff --git a/site/search.html b/site/search.html new file mode 100644 index 00000000..59ffd895 --- /dev/null +++ b/site/search.html @@ -0,0 +1,121 @@ + + + + + + + + + + + + + Search — couchbeam v2.0.0 + + + + + + + + + + + +
+ + + + + + + +
+
+ + + + + +
+
+
+ + + diff --git a/src/couchbeam.erl b/src/couchbeam.erl index 3f917a06..c048df4e 100644 --- a/src/couchbeam.erl +++ b/src/couchbeam.erl @@ -66,7 +66,7 @@ %% -------------------------------------------------------------------- %% @doc Create a server for connectiong to a CouchDB node -%% @equiv server_connection("127.0.0.1", 5984, "", [], false) +%% @equiv server_connection(URL, Options) server_connection() -> URL = couchbeam_util:binary_env("COUCHDB_URL", "http://127.0.0.1:5984"), ADMIN = couchbeam_util:binary_env("COUCHDB_ADMIN", "admin"), @@ -152,7 +152,6 @@ server_connection(Host, Port, Prefix, Options) -> server_connection(Url, Options). %% @doc Get Information from the server -%% @spec server_info(server()) -> {ok, iolist()} server_info(#server{url=Url, options=Opts}) -> case hackney:get(Url, [], <<>>, Opts) of {ok, 200, _, Ref} -> @@ -167,28 +166,25 @@ server_info(#server{url=Url, options=Opts}) -> end. %% @doc Get one uuid from the server -%% @spec get_uuid(server()) -> lists() get_uuid(Server) -> couchbeam_uuids:get_uuids(Server, 1). %% @doc Get a list of uuids from the server -%% @spec get_uuids(server(), integer()) -> lists() get_uuids(Server, Count) -> couchbeam_uuids:get_uuids(Server, Count). -%% @doc Handle replication. Pass an object containting all informations -%% It allows to pass for example an authentication info +%% @doc Handle replication. Pass a map containing all information. +%% It allows passing authentication info, etc. %% ``` -%% RepObj = {[ -%% {<<"source">>, <<"sourcedb">>}, -%% {<<"target">>, <<"targetdb">>}, -%% {<<"create_target">>, true} -%% ]} +%% RepObj = #{ +%% <<"source">> => <<"sourcedb">>, +%% <<"target">> => <<"targetdb">>, +%% <<"create_target">> => true +%% }. %% replicate(Server, RepObj). %% ''' %% -%% @spec replicate(Server::server(), RepObj::{list()}) %% -> {ok, Result}|{error, Error} replicate(#server{}=Server, RepObj) when is_map(RepObj) -> case open_db(Server, <<"_replicator">>) of @@ -199,13 +195,12 @@ replicate(Server, Props) when is_list(Props) -> replicate(Server, maps:from_list(Props)). %% @doc Handle replication. -%% @spec replicate(Server::server(), Source::string(), Target::target()) %% -> {ok, Result}|{error, Error} replicate(Server, Source, Target) -> replicate(Server, Source, Target, []). %% @doc handle Replication. Allows to pass options with source and -%% target. Source and target can be either simple URI strings or +%% target. Source and target can be either simple URI strings or %% complex document structures with authentication. Options is a Json object. %% ex: %% ``` @@ -215,9 +210,13 @@ replicate(Server, Source, Target) -> %% %% %% Complex replication with authentication %% Source = "http://user:pass@remote.com:5984/db", -%% Target = {[{<<"url">>, <<"http://localhost:5984/target_db">>}, -%% {<<"auth">>, {[{<<"basic">>, {[{<<"username">>, <<"user">>}, -%% {<<"password">>, <<"pass">>}]}}]}}]}, +%% Target = #{ +%% <<"url">> => <<"http://localhost:5984/target_db">>, +%% <<"auth">> => #{ +%% <<"basic">> => #{<<"username">> => <<"user">>, +%% <<"password">> => <<"pass">>} +%% } +%% }, %% couchbeam:replicate(S, Source, Target, [{<<"continuous">>, true}]). %% ''' replicate(Server, Source, Target, {Props}) -> @@ -232,11 +231,9 @@ replicate(Server, Source, Target, Options) -> replicate(Server, RepProp). %% @doc get list of databases on a CouchDB node -%% @spec all_dbs(server()) -> {ok, iolist()} all_dbs(#server{}=Server) -> all_dbs(Server, []). %% @doc get list of databases on a CouchDB node with optional filter -%% @spec all_dbs(server(), view_options()) -> {ok, iolist()} all_dbs(#server{url=ServerUrl, options=Opts}, Options) -> Args = couchbeam_view:parse_view_options(Options), Url = hackney_url:make_url(ServerUrl, <<"_all_dbs">>, Args#view_query_args.options), @@ -277,7 +274,6 @@ view_cleanup(#db{server=Server, name=DbName, options=Opts}) -> end. %% @doc test if db with dbname exists on the CouchDB node -%% @spec db_exists(server(), string()) -> boolean() db_exists(#server{url=ServerUrl, options=Opts}, DbName) -> Url = hackney_url:make_url(ServerUrl, couchbeam_util:dbname(DbName), []), case couchbeam_httpc:db_request(head, Url, [], <<>>, Opts, [200]) of @@ -307,7 +303,6 @@ create_db(Server, DbName, Options) -> %% Params is a list of optionnal query argument you want to pass to the %% db. Useful for bigcouch for example. %% -%% @spec create_db(Server::server(), DbName::string(), %% Options::optionList(), Params::list()) -> {ok, db()|{error, Error}} create_db(#server{url=ServerUrl, options=Opts}=Server, DbName0, Options, Params) -> @@ -331,7 +326,6 @@ open_db(Server, DbName) -> open_db(Server, DbName, []). %% @doc Create a client for connection to a database -%% @spec open_db(Server::server(), DbName::string(), Options::optionList()) %% -> {ok, db()} open_db(#server{options=Opts}=Server, DbName, Options) -> Options1 = couchbeam_util:propmerge1(Options, Opts), @@ -352,7 +346,6 @@ open_or_create_db(Server, DbName, Options) -> %% @doc Create a client for connecting to a database and create the %% database if needed. -%% @spec open_or_create_db(server(), string(), list(), list()) -> {ok, db()|{error, Error}} open_or_create_db(#server{url=ServerUrl, options=Opts}=Server, DbName0, Options, Params) -> @@ -376,7 +369,6 @@ delete_db(#db{server=Server, name=DbName}) -> delete_db(Server, DbName). %% @doc delete database -%% @spec delete_db(server(), DbName) -> {ok, iolist()|{error, Error}} delete_db(#server{url=ServerUrl, options=Opts}, DbName) -> Url = hackney_url:make_url(ServerUrl, couchbeam_util:dbname(DbName), []), Resp = couchbeam_httpc:request(delete, Url, [], <<>>, Opts), @@ -388,7 +380,6 @@ delete_db(#server{url=ServerUrl, options=Opts}, DbName) -> end. %% @doc get database info -%% @spec db_info(db()) -> {ok, iolist()|{error, Error}} db_info(#db{server=Server, name=DbName, options=Opts}) -> Url = hackney_url:make_url(couchbeam_httpc:server_url(Server), couchbeam_util:dbname(DbName), []), case couchbeam_httpc:db_request(get, Url, [], <<>>, Opts, [200]) of @@ -402,7 +393,6 @@ db_info(#db{server=Server, name=DbName, options=Opts}) -> end. %% @doc test if doc with uuid exists in the given db -%% @spec doc_exists(db(), string()) -> boolean() doc_exists(#db{server=Server, options=Opts}=Db, DocId) -> DocId1 = couchbeam_util:encode_docid(DocId), Url = hackney_url:make_url(couchbeam_httpc:server_url(Server), couchbeam_httpc:doc_url(Db, DocId1), []), @@ -418,7 +408,6 @@ open_doc(Db, DocId) -> %% @doc open a document %% Params is a list of query argument. Have a look in CouchDb API -%% @spec open_doc(Db::db(), DocId::string(), Params::list()) %% -> {ok, Doc}|{error, Error} open_doc(#db{server=Server, options=Opts}=Db, DocId, Params) -> DocId1 = couchbeam_util:encode_docid(DocId), @@ -486,17 +475,16 @@ save_doc(Db, Doc) -> %% @doc save a *document %% A document is a Json object like this one: %% -%% ```{[ -%% {<<"_id">>, <<"myid">>}, -%% {<<"title">>, <<"test">>} -%% ]}''' +%% ```#{ +%% <<"_id">> => <<"myid">>, +%% <<"title">> => <<"test">> +%% }''' %% %% Options are arguments passed to the request. This function return a %% new document with last revision and a docid. If _id isn't specified in %% document it will be created. Id is created by extracting an uuid from %% the couchdb node. %% -%% @spec save_doc(Db::db(), Doc, Options::list()) -> {ok, Doc1}|{error, Error} save_doc(Db, Doc, Options) -> save_doc(Db, Doc, [], Options). @@ -504,10 +492,10 @@ save_doc(Db, Doc, Options) -> %% @doc save a *document with all its attacjments %% A document is a Json object like this one: %% -%% ```{[ -%% {<<"_id">>, <<"myid">>}, -%% {<<"title">>, <<"test">>} -%% ]}''' +%% ```#{ +%% <<"_id">> => <<"myid">>, +%% <<"title">> => <<"test">> +%% }''' %% %% Options are arguments passed to the request. This function return a %% new document with last revision and a docid. If _id isn't specified in @@ -592,7 +580,6 @@ delete_doc(Db, Doc) -> %% if you want to make sure the doc it emptied on delete, use the option %% {empty_on_delete, true} or pass a doc with just _id and _rev %% members. -%% @spec delete_doc(Db, Doc, Options) -> {ok,Result}|{error,Error} delete_doc(Db, Doc, Options) -> delete_docs(Db, [Doc], Options). @@ -605,7 +592,6 @@ delete_docs(Db, Docs) -> %% if you want to make sure the doc it emptied on delete, use the option %% {empty_on_delete, true} or pass a doc with just _id and _rev %% members. -%% @spec delete_docs(Db::db(), Docs::list(),Options::list()) -> {ok, Result}|{error, Error} delete_docs(Db, Docs, Options) -> Empty = couchbeam_util:get_value("empty_on_delete", Options, false), @@ -631,7 +617,6 @@ save_docs(Db, Docs) -> save_docs(Db, Docs, []). %% @doc save a list of documents -%% @spec save_docs(Db::db(), Docs::list(),Options::list()) -> {ok, Result}|{error, Error} save_docs(#db{server=Server, options=Opts}=Db, Docs, Options) -> Docs1 = [maybe_docid(Server, Doc) || Doc <- Docs], Options1 = couchbeam_util:parse_options(Options), @@ -819,7 +804,6 @@ put_attachment(Db, DocId, Name, Body)-> put_attachment(Db, DocId, Name, Body, []). %% @doc put an attachment -%% @spec put_attachment(Db::db(), DocId::string(), Name::string(), %% Body::body(), Option::optionList()) -> {ok, iolist()} %% optionList() = [option()] %% option() = {rev, string()} | @@ -890,7 +874,6 @@ delete_attachment(Db, Doc, Name) -> delete_attachment(Db, Doc, Name, []). %% @doc delete a document attachment -%% @spec(db(), string()|list(), string(), list() -> {ok, Result} | {error, Error} delete_attachment(#db{server=Server, options=Opts}=Db, DocOrDocId, Name, Options) -> Options1 = couchbeam_util:parse_options(Options), @@ -954,7 +937,6 @@ ensure_full_commit(#db{server=Server, options=Opts}=Db, Options) -> %% @doc Compaction compresses the database file by removing unused %% sections created during updates. %% See [http://wiki.apache.org/couchdb/Compaction] for more informations -%% @spec compact(Db::db()) -> ok|{error, term()} compact(#db{server=Server, options=Opts}=Db) -> Url = hackney_url:make_url(couchbeam_httpc:server_url(Server), [couchbeam_httpc:db_url(Db), <<"_compact">>], @@ -970,7 +952,6 @@ compact(#db{server=Server, options=Opts}=Db) -> %% @doc Like compact/1 but this compacts the view index from the %% current version of the design document. %% See [http://wiki.apache.org/couchdb/Compaction#View_compaction] for more informations -%% @spec compact(Db::db(), ViewName::string()) -> ok|{error, term()} compact(#db{server=Server, options=Opts}=Db, DesignName) -> Url = hackney_url:make_url(couchbeam_httpc:server_url(Server), [couchbeam_httpc:db_url(Db), <<"_compact">>, diff --git a/src/couchbeam_attachments.erl b/src/couchbeam_attachments.erl index c169394b..f342246b 100644 --- a/src/couchbeam_attachments.erl +++ b/src/couchbeam_attachments.erl @@ -13,17 +13,15 @@ -export([add_inline/3, add_inline/4, add_stub/3, delete_inline/2]). - -%% @spec add_inline(Doc::json_obj(),Content::attachment_content(), -%% AName::string()) -> json_obj() + +-spec add_inline(doc(), iodata(), string() | binary()) -> doc(). %% @doc add attachment to a doc and encode it. Give possibility to send attachments inline. add_inline(Doc, Content, AName) -> AName1 = hackney_bstr:to_binary(AName), ContentType = mimerl:filename(AName1), add_inline(Doc, Content, AName1, ContentType). -%% @spec add_inline(Doc::json_obj(), Content::attachment_content(), -%% AName::string(), ContentType::string()) -> json_obj() +-spec add_inline(doc(), iodata(), string() | binary(), string() | binary()) -> doc(). %% @doc add attachment to a doc and encode it with ContentType fixed. add_inline(Doc, Content, AName, ContentType) -> Data = base64:encode(Content), @@ -34,6 +32,7 @@ add_inline(Doc, Content, AName, ContentType) -> couchbeam_doc:set_value(<<"_attachments">>, Atts1, Doc). +-spec add_stub(doc(), string() | binary(), string() | binary()) -> doc(). add_stub(Doc, Name, ContentType) -> AttName = couchbeam_util:to_binary(Name), Att = #{<<"content_type">> => couchbeam_util:to_binary(ContentType)}, @@ -42,7 +41,7 @@ add_stub(Doc, Name, ContentType) -> couchbeam_doc:set_value(<<"_attachments">>, Atts1, Doc). -%% @spec delete_inline(Doc::json_obj(), AName::string()) -> json_obj() +-spec delete_inline(doc(), string() | binary()) -> doc(). %% @doc delete an attachment record in doc. This is different from delete_attachment %% change is only applied in Doc object. Save_doc should be save to save changes. delete_inline(Doc, AName) when is_list(AName) -> diff --git a/src/couchbeam_changes.erl b/src/couchbeam_changes.erl index 6f63b3ca..9fec260f 100644 --- a/src/couchbeam_changes.erl +++ b/src/couchbeam_changes.erl @@ -175,7 +175,7 @@ stream_next(Ref) -> Pid ! {Ref, stream_next} end). -%% @private +%% internal collect_changes(Ref) -> collect_changes(Ref, []). diff --git a/src/couchbeam_changes_stream.erl b/src/couchbeam_changes_stream.erl index e9252eea..6fdfa50f 100644 --- a/src/couchbeam_changes_stream.erl +++ b/src/couchbeam_changes_stream.erl @@ -368,7 +368,7 @@ system_code_change(Misc, _, _, _) -> %%% removed legacy jsx-driven decoder code -%% @private +%% internal %% parse options to get feed type when it's not passed in a tuple %% to support the old api. @@ -403,14 +403,7 @@ maybe_close(#state{client_ref=nil}) -> maybe_close(#state{client_ref=Ref}) -> hackney:close(Ref). -%post_decode([{}]) -> -% {[]}; -%post_decode([{_Key, _Value} | _Rest] = PropList) -> -% {[ {Key, post_decode(Value)} || {Key, Value} <- PropList ]}; -%post_decode(List) when is_list(List) -> -% [ post_decode(Term) || Term <- List]; -%post_decode(Term) -> -% Term. +%% legacy jsx-driven post_decode removed; maps are used natively -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). diff --git a/src/couchbeam_doc.erl b/src/couchbeam_doc.erl index 0aed94ee..a1d6e49b 100644 --- a/src/couchbeam_doc.erl +++ b/src/couchbeam_doc.erl @@ -12,24 +12,24 @@ delete_value/2, extend/2, extend/3]). -export([get_id/1, get_rev/1, get_idrev/1, is_saved/1]). -%% @spec get_id(Doc::json_obj()) -> binary() +-spec get_id(doc()) -> binary(). %% @doc get document id. get_id(Doc) -> get_value(<<"_id">>, Doc). -%% @spec get_rev(Doc::json_obj()) -> binary() +-spec get_rev(doc()) -> binary(). %% @doc get document revision. get_rev(Doc) -> get_value(<<"_rev">>, Doc). -%% @spec get_idrev(Doc::json_obj()) -> {DocId, DocRev} +-spec get_idrev(doc()) -> {binary(), binary()}. %% @doc get a tuple containing docucment id and revision. get_idrev(Doc) -> DocId = get_value(<<"_id">>, Doc), DocRev = get_value(<<"_rev">>, Doc), {DocId, DocRev}. -%% @spec is_saved(Doc::json_obj()) -> boolean() +-spec is_saved(doc()) -> boolean(). %% @doc If document have been saved (revision is defined) return true, %% else, return false. is_saved(Doc) -> @@ -38,22 +38,21 @@ is_saved(Doc) -> _ -> true end. -%% @spec set_value(Key::key_val(), Value::term(), JsonObj::json_obj()) -> term() +-spec set_value(binary() | list(), term(), doc()) -> doc(). %% @doc set a value for a key in jsonobj. If key exists it will be updated. set_value(Key, Value, JsonObj) when is_list(Key)-> set_value(list_to_binary(Key), Value, JsonObj); set_value(Key, Value, JsonObj) when is_binary(Key), is_map(JsonObj) -> maps:put(Key, Value, JsonObj). -%% @spec get_value(Key::key_val(), JsonObj::json_obj()) -> term() -%% @type key_val() = lis() | binary() +-spec get_value(binary() | list(), doc()) -> term(). %% @doc Returns the value of a simple key/value property in json object %% Equivalent to get_value(Key, JsonObj, undefined). get_value(Key, JsonObj) -> get_value(Key, JsonObj, undefined). -%% @spec get_value(Key::lis() | binary(), JsonObj::json_obj(), Default::term()) -> term() +-spec get_value(binary() | list(), doc(), term()) -> term(). %% @doc Returns the value of a simple key/value property in json object %% function from erlang_couchdb get_value(Key, JsonObj, Default) when is_list(Key) -> @@ -62,7 +61,7 @@ get_value(Key, JsonObj, Default) when is_binary(Key), is_map(JsonObj) -> maps:get(Key, JsonObj, Default). -%% @spec take_value(Key::key_val(), JsonObj::json_obj()) -> {term(), json_obj()} +-spec take_value(binary() | list(), doc()) -> {term(), doc()}. %% @doc Returns the value of a simple key/value property in json object and deletes %% it form json object %% Equivalent to take_value(Key, JsonObj, undefined). @@ -70,8 +69,7 @@ take_value(Key, JsonObj) -> take_value(Key, JsonObj, undefined). -%% @spec take_value(Key::key_val() | binary(), JsonObj::json_obj(), -%% Default::term()) -> {term(), json_obj()} +-spec take_value(binary() | list(), doc(), term()) -> {term(), doc()}. %% @doc Returns the value of a simple key/value property in json object and deletes %% it from json object take_value(Key, JsonObj, Default) when is_list(Key) -> @@ -84,20 +82,19 @@ take_value(Key, JsonObj, Default) when is_binary(Key), is_map(JsonObj) -> {Default, JsonObj} end. -%% @spec delete_value(Key::key_val(), JsonObj::json_obj()) -> json_obj() +-spec delete_value(binary() | list(), doc()) -> doc(). %% @doc Deletes all entries associated with Key in json object. delete_value(Key, JsonObj) when is_list(Key) -> delete_value(list_to_binary(Key), JsonObj); delete_value(Key, JsonObj) when is_binary(Key), is_map(JsonObj) -> maps:remove(Key, JsonObj). -%% @spec extend(Key::binary(), Value::json_term(), JsonObj::json_obj()) -> json_obj() +-spec extend(binary(), ejson_term(), doc()) -> doc(). %% @doc extend a jsonobject by key, value extend(Key, Value, JsonObj) -> extend({Key, Value}, JsonObj). -%% @spec extend(Prop::property(), JsonObj::json_obj()) -> json_obj() -%% @type property() = json_obj() | tuple() +-spec extend(term(), doc()) -> doc(). %% @doc extend a jsonobject by a property, list of property or another jsonobject extend([], JsonObj) -> JsonObj; @@ -109,7 +106,6 @@ extend([Prop|R], JsonObj)-> extend({Key, Value}, JsonObj) -> set_value(Key, Value, JsonObj). -%% @private %% maps only in new API diff --git a/src/couchbeam_ejson.erl b/src/couchbeam_ejson.erl index d1ca4ea9..a384e970 100644 --- a/src/couchbeam_ejson.erl +++ b/src/couchbeam_ejson.erl @@ -36,7 +36,7 @@ decode(D) when is_binary(D) -> end; decode(D) -> decode(iolist_to_binary(D)). -%% post_decode was previously used to convert jsx proplists / {[...]} objects +%% post_decode was previously used to convert jsx proplists / old tuple-wrapped object forms %% to ejson. Since objects are now maps, it is identity. post_decode(Term) -> Term. diff --git a/src/couchbeam_httpc.erl b/src/couchbeam_httpc.erl index aac4d9e7..5345540a 100644 --- a/src/couchbeam_httpc.erl +++ b/src/couchbeam_httpc.erl @@ -121,14 +121,16 @@ db_resp_body(Ref) -> <<>> end. +-spec server_url(server()) -> binary(). %% @doc Asemble the server URL for the given client -%% @spec server_url({Host, Port}) -> iolist() server_url(#server{url=Url}) -> Url. +-spec db_url(db()) -> binary(). db_url(#db{name=DbName}) -> DbName. +-spec doc_url(db(), binary()) -> binary(). doc_url(Db, DocId) -> iolist_to_binary([db_url(Db), <<"/">>, DocId]). diff --git a/src/couchbeam_util.erl b/src/couchbeam_util.erl index 7b966574..e7e86d2a 100644 --- a/src/couchbeam_util.erl +++ b/src/couchbeam_util.erl @@ -243,14 +243,14 @@ shutdown_sync(Pid) -> erlang:demonitor(MRef, [flush]) end. -%% @spec start_app_deps(App :: atom()) -> ok +-spec start_app_deps(atom()) -> ok. %% @doc Start depedent applications of App. start_app_deps(App) -> {ok, DepApps} = application:get_key(App, applications), [ensure_started(A) || A <- DepApps], ok. -%% @spec ensure_started(Application :: atom()) -> ok +-spec ensure_started(atom()) -> ok. %% @doc Start the named application if not already started. ensure_started(App) -> case application:start(App) of diff --git a/src/couchbeam_uuids.erl b/src/couchbeam_uuids.erl index 7a7290bf..8264a4f6 100644 --- a/src/couchbeam_uuids.erl +++ b/src/couchbeam_uuids.erl @@ -34,8 +34,8 @@ random() -> utc_random() -> utc_suffix(hackney_bstr:to_hex(crypto:strong_rand_bytes(9))). +-spec get_uuids(server(), integer()) -> list(). %% @doc Get a list of uuids from the server -%% @spec get_uuids(server(), integer()) -> lists() get_uuids(Server, Count) -> gen_server:call(?MODULE, {get_uuids, Server, Count}, infinity). @@ -43,16 +43,16 @@ get_uuids(Server, Count) -> %% Function: start_link/0 %% Description: Starts the server %%-------------------------------------------------------------------- +-spec start_link() -> {ok, pid()} | {error, term()}. %% @doc Starts the couchbeam process linked to the calling process. Usually %% invoked by the supervisor couchbeam_sup -%% @spec start_link() -> {ok, pid()} start_link() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). %%--------------------------------------------------------------------------- %% gen_server callbacks %%--------------------------------------------------------------------------- -%% @private +%% internal init(_) -> process_flag(trap_exit, true), diff --git a/src/couchbeam_view.erl b/src/couchbeam_view.erl index a6bfe338..19333cca 100644 --- a/src/couchbeam_view.erl +++ b/src/couchbeam_view.erl @@ -75,7 +75,7 @@ fetch(Db, ViewName) -> %% | {inclusive_end, boolean()} | {reduce, boolean()} | reduce | include_docs | conflicts %% | {keys, list(binary())} %% | async_query -%%

See {@link couchbeam_view:stream/4} for more information about +%%

See {@link couchbeam_view:stream/3} for more information about %% options.

%%

Return: {ok, Rows} or {error, Error}

fetch(Db, ViewName, Options) -> @@ -119,7 +119,7 @@ show(Db, ShowName) -> show(Db, ShowName, DocId) -> show(Db, ShowName, DocId, []). --type show_option() :: {'query_string', binary()}. % "foo=bar&baz=biz" +-type show_option() :: {'query_string', binary()}. % example: "foo=bar&baz=biz" -type show_options() :: [show_option()]. -spec show(db(), {binary(), binary()}, 'null' | binary(), show_options()) -> @@ -163,7 +163,7 @@ show_doc_id(<>) -> [<<"/">>, couchbeam_util:encode_docid(DocId)]. -spec stream(Db::db(), ViewName::'all_docs' | {DesignName::design_name(), ViewName::view_name()}) -> {ok, StartRef::term(), ViewPid::pid()} | {error, term()}. -%% @equiv stream(Db, ViewName, Client, []) +%% @equiv stream(Db, ViewName, []) stream(Db, ViewName) -> stream(Db, ViewName, []). @@ -171,63 +171,32 @@ stream(Db, ViewName) -> ViewName::view_name()}, Options::view_options()) -> {ok, StartRef::term()} | {error, term()}. %% @doc stream view results to a pid -%%

Db: a db record

-%%

ViewName: 'all_docs' to get all docs or {DesignName, -%% ViewName}

-%%

Client: pid where to send view events where events are: -%%

-%%
{row, StartRef, done}
-%%
All view results have been fetched
-%%
{row, StartRef, Row :: ejson_object()}
-%%
A row in the view
-%%
{error, StartRef, Error}
-%% happend. -%%

-%%

Options :: view_options() [{key, binary()}
-%%    | descending
-%%    | {skip, integer()}
-%%    | group | {group_level, integer()}
-%%    | {inclusive_end, boolean()} | {reduce, boolean()} | reduce | include_docs | conflicts
-%%    | {keys, list(binary())}
-%%    | `{stream_to, Pid}': the pid where the changes will be sent,
-%%      by default the current pid. Used for continuous and longpoll
-%%      connections
-%% -%%
    -%%
  • {key, Key}: key value
  • -%%
  • {start_docid, DocId} | {startkey_docid, DocId}: document id to start with (to allow pagination -%% for duplicate start keys
  • -%%
  • {end_docid, DocId} | {endkey_docid, DocId}: last document id to include in the result (to -%% allow pagination for duplicate endkeys)
  • -%%
  • {start_key, Key}: start result from key value
  • -%%
  • {end_key, Key}: end result from key value
  • -%%
  • {limit, Limit}: Limit the number of documents in the result
  • -%%
  • {stale, Stale}: If stale=ok is set, CouchDB will not refresh the view -%% even if it is stale, the benefit is a an improved query latency. If -%% stale=update_after is set, CouchDB will update the view after the stale -%% result is returned. If stale=false is set, CouchDB will update the view before -%% the query. The default value of this parameter is update_after.
  • -%%
  • descending: reverse the result
  • -%%
  • {skip, N}: skip n number of documents
  • -%%
  • group: the reduce function reduces to a single result -%% row.
  • -%%
  • {group_level, Level}: the reduce function reduces to a set -%% of distinct keys.
  • -%%
  • {reduce, boolean()}: whether to use the reduce function of the view. It defaults to -%% true, if a reduce function is defined and to false otherwise.
  • -%%
  • include_docs: automatically fetch and include the document -%% which emitted each view entry
  • -%%
  • {inclusive_end, boolean()}: Controls whether the endkey is included in -%% the result. It defaults to true.
  • -%%
  • conflicts: include conflicts
  • -%%
  • {keys, [Keys]}: to pass multiple keys to the view query
  • -%%

+%% Db: a db record +%% ViewName: 'all_docs' to get all docs or {DesignName, ViewName} +%% Client receives messages: +%% - {row, StartRef, done} All rows have been fetched +%% - {row, StartRef, Row :: ejson_object()} A row in the view +%% - {error, StartRef, Error} An error occurred; stream closed +%% Options include (see couchbeam_view:parse_view_options/1): +%% - {key, Key} +%% - {start_docid, DocId} | {startkey_docid, DocId} +%% - {end_docid, DocId} | {endkey_docid, DocId} +%% - {start_key, Key} | {end_key, Key} +%% - {limit, N} +%% - {stale, ok | update_after | false} +%% - descending | {skip, N} +%% - group | {group_level, integer()} +%% - reduce | {reduce, boolean()} +%% - include_docs | conflicts | {inclusive_end, boolean()} +%% - {keys, [Key]} +%% - {stream_to, Pid} + + + %% -%%

Return {ok, StartRef, ViewPid} or {error, - %Error}. Ref can be -%% used to disctint all changes from this pid. ViewPid is the pid of -%% the view loop process. Can be used to monitor it or kill it -%% when needed.

+%% Return: {ok, StartRef, ViewPid} or {error, Reason}. +%% Ref can be used to distinguish streams from this pid. +%% ViewPid is the pid of the view loop process. stream(Db, ViewName, Options) -> {To, Options1} = case proplists:get_value(stream_to, Options) of undefined -> @@ -334,7 +303,7 @@ first(Db, ViewName) -> %% | group | {group_level, integer()} %% | {inclusive_end, boolean()} | {reduce, boolean()} | reduce | include_docs | conflicts %% | {keys, list(binary())} -%%

See {@link couchbeam_view:stream/4} for more information about +%%

See {@link couchbeam_view:stream/3} for more information about %% options.

%%

Return: {ok, Row} or {error, Error}

first(Db, ViewName, Options) -> @@ -511,7 +480,7 @@ parse_view_options([{Key, Value}|Rest], #view_query_args{options=Opts}=Args) parse_view_options([_|Rest], Args) -> parse_view_options(Rest, Args). -%% @private +%% internal make_view(#db{server=Server}=Db, ViewName, Options, Fun) -> Args = parse_view_options(Options), diff --git a/src/gen_changes.erl b/src/gen_changes.erl index 1b3eab0a..72f0af03 100644 --- a/src/gen_changes.erl +++ b/src/gen_changes.erl @@ -50,7 +50,6 @@ cast(Dest, Request) -> %% @doc create a gen_changes process as part of a supervision tree. %% The function should be called, directly or indirectly, by the supervisor. -%% @spec start_link(Module, Db::db(), Options::changesoptions(), %% InitArgs::list()) -> term() %% changesoptions() = [changeoption()] %% changeoption() = {include_docs, string()} | From 1383ca7a9ebfe26c326ad4853346d3542be7b370 Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Thu, 4 Sep 2025 23:24:15 +0200 Subject: [PATCH 6/7] Hex: configure rebar3_hex provider for docs; output ExDoc to doc/ --- rebar.config | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/rebar.config b/rebar.config index 5f2a7cb1..6a1d062c 100644 --- a/rebar.config +++ b/rebar.config @@ -5,13 +5,13 @@ {platform_define, "^(2[3-9])", 'USE_CRYPTO_MAC'}]}. %% ExDoc plugin for generating HTML docs -{plugins, [rebar3_ex_doc]}. +{plugins, [rebar3_ex_doc, rebar3_hex]}. %% ExDoc settings {ex_doc, [ {source_url, "https://github.com/benoitc/couchbeam"}, {main, "readme"}, - {output, "site"}, + {output, "doc"}, {extras, [ {"README.md", #{title => "Readme"}}, {"NEWS.md", #{title => "Changelog"}}, @@ -20,6 +20,12 @@ ]} ]}. +%% Hex.pm configuration +%% - Use ExDoc for docs when running `rebar3 hex docs` +{hex, [ + {doc, #{provider => ex_doc}} +]}. + {deps, [ {hackney, "1.25.0"} ]}. From 59c71c88707cc688ecba6cad5bc6580a67b860d1 Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Thu, 4 Sep 2025 23:33:42 +0200 Subject: [PATCH 7/7] Housekeeping: remove generated site/ docs and ignore folder --- .gitignore | 1 + site/.build | 34 - site/404.html | 123 - site/api-reference.html | 254 -- site/couchbeam.epub | Bin 77049 -> 0 bytes site/couchbeam.html | 2386 ----------------- site/couchbeam_app.html | 218 -- site/couchbeam_attachments.html | 402 --- site/couchbeam_changes.html | 566 ---- site/couchbeam_changes_stream.html | 374 --- site/couchbeam_changes_sup.html | 224 -- site/couchbeam_doc.html | 849 ------ site/couchbeam_ejson.html | 499 ---- site/couchbeam_httpc.html | 568 ---- site/couchbeam_sup.html | 218 -- site/couchbeam_util.html | 972 ------- site/couchbeam_uuids.html | 544 ---- site/couchbeam_view.html | 1508 ----------- site/couchbeam_view_stream.html | 344 --- site/couchbeam_view_sup.html | 224 -- site/dist/html-DPJLHKSM.js | 222 -- site/dist/html-erlang-DQDXQC7W.css | 6 - .../dist/lato-latin-400-normal-W7754I4D.woff2 | Bin 23580 -> 0 bytes .../dist/lato-latin-700-normal-2XVSBPG4.woff2 | Bin 23040 -> 0 bytes .../lato-latin-ext-400-normal-N27NCBWW.woff2 | Bin 5472 -> 0 bytes .../lato-latin-ext-700-normal-Q2L5DVMW.woff2 | Bin 5368 -> 0 bytes site/dist/remixicon-QPNJX265.woff2 | Bin 2096 -> 0 bytes site/dist/search_data-37149571.js | 1 - site/dist/sidebar_items-A03F7C15.js | 1 - site/gen_changes.html | 554 ---- site/index.html | 10 - site/json_stream_parse.html | 248 -- site/license.html | 170 -- site/news.html | 192 -- site/notice.html | 164 -- site/readme.html | 294 -- site/search.html | 121 - 37 files changed, 1 insertion(+), 12290 deletions(-) delete mode 100644 site/.build delete mode 100644 site/404.html delete mode 100644 site/api-reference.html delete mode 100644 site/couchbeam.epub delete mode 100644 site/couchbeam.html delete mode 100644 site/couchbeam_app.html delete mode 100644 site/couchbeam_attachments.html delete mode 100644 site/couchbeam_changes.html delete mode 100644 site/couchbeam_changes_stream.html delete mode 100644 site/couchbeam_changes_sup.html delete mode 100644 site/couchbeam_doc.html delete mode 100644 site/couchbeam_ejson.html delete mode 100644 site/couchbeam_httpc.html delete mode 100644 site/couchbeam_sup.html delete mode 100644 site/couchbeam_util.html delete mode 100644 site/couchbeam_uuids.html delete mode 100644 site/couchbeam_view.html delete mode 100644 site/couchbeam_view_stream.html delete mode 100644 site/couchbeam_view_sup.html delete mode 100644 site/dist/html-DPJLHKSM.js delete mode 100644 site/dist/html-erlang-DQDXQC7W.css delete mode 100644 site/dist/lato-latin-400-normal-W7754I4D.woff2 delete mode 100644 site/dist/lato-latin-700-normal-2XVSBPG4.woff2 delete mode 100644 site/dist/lato-latin-ext-400-normal-N27NCBWW.woff2 delete mode 100644 site/dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 delete mode 100644 site/dist/remixicon-QPNJX265.woff2 delete mode 100644 site/dist/search_data-37149571.js delete mode 100644 site/dist/sidebar_items-A03F7C15.js delete mode 100644 site/gen_changes.html delete mode 100644 site/index.html delete mode 100644 site/json_stream_parse.html delete mode 100644 site/license.html delete mode 100644 site/news.html delete mode 100644 site/notice.html delete mode 100644 site/readme.html delete mode 100644 site/search.html diff --git a/.gitignore b/.gitignore index dac820d4..4da82353 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ mime.types .idea *.im *.crashdump +site/ diff --git a/site/.build b/site/.build deleted file mode 100644 index 79ca836f..00000000 --- a/site/.build +++ /dev/null @@ -1,34 +0,0 @@ -404.html -api-reference.html -couchbeam.html -couchbeam_app.html -couchbeam_attachments.html -couchbeam_changes.html -couchbeam_changes_stream.html -couchbeam_changes_sup.html -couchbeam_doc.html -couchbeam_ejson.html -couchbeam_httpc.html -couchbeam_sup.html -couchbeam_util.html -couchbeam_uuids.html -couchbeam_view.html -couchbeam_view_stream.html -couchbeam_view_sup.html -dist/html-DPJLHKSM.js -dist/html-erlang-DQDXQC7W.css -dist/lato-latin-400-normal-W7754I4D.woff2 -dist/lato-latin-700-normal-2XVSBPG4.woff2 -dist/lato-latin-ext-400-normal-N27NCBWW.woff2 -dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 -dist/remixicon-QPNJX265.woff2 -dist/search_data-37149571.js -dist/sidebar_items-A03F7C15.js -gen_changes.html -index.html -json_stream_parse.html -license.html -news.html -notice.html -readme.html -search.html diff --git a/site/404.html b/site/404.html deleted file mode 100644 index f07fba1b..00000000 --- a/site/404.html +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - 404 — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - -

- Page not found -

- -

Sorry, but the page you were trying to get to, does not exist. You -may want to try searching this site using the sidebar - - or using our API Reference page - -to find what you were looking for.

- -
-
-
- - - diff --git a/site/api-reference.html b/site/api-reference.html deleted file mode 100644 index eef585af..00000000 --- a/site/api-reference.html +++ /dev/null @@ -1,254 +0,0 @@ - - - - - - - - - - - API Reference — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - -
-
-

API Reference couchbeam v#2.0.0

- - - - View Source - - -
- -
-

Modules

-
-
-
- couchbeam - -
- -
-
- - -
-
- - -

This module contains utilities to manage attachments

- -
-
- - -
- - -
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
- -
- - -
-
-
- gen_changes - -
- -

gen_changes CouchDB continuous changes consumer behavior This behaviour allows you to create easily a server that consume Couchdb continuous changes

- -
-
- - -
- -
-
- - -
- -
-
-
- - - diff --git a/site/couchbeam.epub b/site/couchbeam.epub deleted file mode 100644 index f7193fe454191ac0003e4623a1fcfc1e4ccb1f73..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77049 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%0AgEyRia2M@}*a>&AAp1PPTpgy+H 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 diff --git a/site/couchbeam.html b/site/couchbeam.html deleted file mode 100644 index e54e42ff..00000000 --- a/site/couchbeam.html +++ /dev/null @@ -1,2386 +0,0 @@ - - - - - - - - - - - couchbeam — couchbeam v2.0.0 - - - - - - - - - - - - - - - diff --git a/site/couchbeam_app.html b/site/couchbeam_app.html deleted file mode 100644 index 5b630038..00000000 --- a/site/couchbeam_app.html +++ /dev/null @@ -1,218 +0,0 @@ - - - - - - - - - - - couchbeam_app — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - -
-
-

- couchbeam_app - (couchbeam v2.0.0) - -

- - - - View Source - - -
- - -
- -
-

- - - - Summary -

-
-

- Functions -

- - - -
-
- stop(State) - -
- -
- -
- -
- - -
-

- - - - Functions -

-
-
- -
- - - -
-

start(Type, StartArgs)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

stop(State)

- - - - - - -
-
- -
- - -
-
- -
-
- - -
-
-
- - - diff --git a/site/couchbeam_attachments.html b/site/couchbeam_attachments.html deleted file mode 100644 index 419c273b..00000000 --- a/site/couchbeam_attachments.html +++ /dev/null @@ -1,402 +0,0 @@ - - - - - - - - - - - couchbeam_attachments — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - -
-
-

- couchbeam_attachments - (couchbeam v2.0.0) - -

- - - - View Source - - -
- - -
-

This module contains utilities to manage attachments

-
- -
- -
-

- - - - Summary -

-
-

- Types -

- -
-
- doc/0 - -
- -
- -
- - -
- -
-
-

- Functions -

- -
- - -

add attachment to a doc and encode it. Give possibility to send attachments inline.

- -
- -
- - -

add attachment to a doc and encode it with ContentType fixed.

- -
- - - -
- - -

delete an attachment record in doc. This is different from delete_attachment change is only applied in Doc object. Save_doc should be save to save changes.

- -
- -
- -
- - -
-

- - - - Types -

-
-
- -
- - - -
-

doc/0

- - - - - - -
-
- -
- -
- -
-type doc() :: ejson_object().
- -
- - -
-
-
- -
- - - -
-

ejson_object/0

- - - - - - -
-
- -
- -
- -
-type ejson_object() :: map().
- -
- - -
-
- -
-
- -
-

- - - - Functions -

-
-
- -
- - - -
-

add_inline(Doc, Content, AName)

- - - - - - -
-
- -
- -
- -
-spec add_inline(doc(), iodata(), string() | binary()) -> doc().
- -
- -

add attachment to a doc and encode it. Give possibility to send attachments inline.

-
-
-
- -
- - - -
-

add_inline(Doc, Content, AName, ContentType)

- - - - - - -
-
- -
- -
- -
-spec add_inline(doc(), iodata(), string() | binary(), string() | binary()) -> doc().
- -
- -

add attachment to a doc and encode it with ContentType fixed.

-
-
-
- -
- - - -
-

add_stub(Doc, Name, ContentType)

- - - - - - -
-
- -
- -
- -
-spec add_stub(doc(), string() | binary(), string() | binary()) -> doc().
- -
- - -
-
-
- -
- - - -
-

delete_inline(Doc, AName)

- - - - - - -
-
- -
- -
- -
-spec delete_inline(doc(), string() | binary()) -> doc().
- -
- -

delete an attachment record in doc. This is different from delete_attachment change is only applied in Doc object. Save_doc should be save to save changes.

-
-
- -
-
- - -
-
-
- - - diff --git a/site/couchbeam_changes.html b/site/couchbeam_changes.html deleted file mode 100644 index 06e856bd..00000000 --- a/site/couchbeam_changes.html +++ /dev/null @@ -1,566 +0,0 @@ - - - - - - - - - - - couchbeam_changes — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - -
-
-

- couchbeam_changes - (couchbeam v2.0.0) - -

- - - - View Source - - -
- - -
- -
-

- - - - Summary -

-
-

- Types -

- -
- - -
- -
- - -
- -
-
- db/0 - -
- -
- -
-
- server/0 - -
- -
- -
-
-

- Functions -

- -
- - -
- -
-
- follow(Db) - -
- -
- -
- - -

Stream changes to a pid

- -
- -
- - -
- -
- - -

fetch all changes at once using a normal or longpoll connections.

- -
- -
- - -
- -
- -
- - -
-

- - - - Types -

-
-
- -
- - - -
-

changes_option/0

- - - - - - -
-
- -
- -
- -
-type changes_option() ::
-          continuous | longpoll | normal | include_docs |
-          {since, integer()} |
-          {timeout, integer()} |
-          heartbeat |
-          {heartbeat, integer()} |
-          {filter, string()} |
-          {filter, string(), [{string(), string() | integer()}]} |
-          conflicts |
-          {style, string()} |
-          descending.
- -
- - -
-
-
- -
- - - -
-

changes_options/0

- - - - - - -
-
- -
- -
- -
-type changes_options() :: [changes_option()].
- -
- - -
-
-
- -
- - - -
-

db/0

- - - - - - -
-
- -
- -
- -
-type db() :: #db{server :: server(), name :: binary(), options :: list()}.
- -
- - -
-
-
- -
- - - -
-

server/0

- - - - - - -
-
- -
- -
- -
-type server() :: #server{url :: term(), options :: list()}.
- -
- - -
-
- -
-
- -
-

- - - - Functions -

-
-
- -
- - - -
-

cancel_stream(Ref)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

follow(Db)

- - - - - - -
-
- -
- -
- -
-spec follow(Db :: db()) -> {ok, StreamRef :: atom()} | {error, term()}.
- -
- - -
-
-
- -
- - - -
-

follow(Db, Options)

- - - - - - -
-
- -
- -
- -
-spec follow(Db :: db(), Options :: changes_options()) -> {ok, StreamRef :: atom()} | {error, term()}.
- -
- -

Stream changes to a pid

Db : a db record

Client : pid or callback where to send changes events where events are The pid receive these events:

{change, StartRef, {done, Lastseq::integer()}
Connection terminated or you got all changes
{change, StartRef, Row :: ejson_object()}
Line of change
{error, LastSeq::integer(), Msg::term()}
Got an error, connection is closed when an error happend.
LastSeq is the last sequence of changes.

While the callbac could be like:

       fun({done, LastSeq}) ->
-           ok;
-       fun({done, LastSeq}) ->
-           ok;
-       fun({done, LastSeq}) ->
-           ok.

>Options :: changes_stream_options() [continuous
-     | longpoll
-     | normal
-     | include_docs
-     | {since, integer() | now}
-     | {timeout, integer()}
-     | heartbeat | {heartbeat, integer()}
-     | {filter, string()} | {filter, string(), list({string(), string() | integer()})}
-     | {view, string()},
-     | {docids, list))},
-     | {stream_to, pid()},
-     | {async, once | normal}]
  • continuous | longpoll | normal: set the type of changes feed to get
  • include_doc: if you want to include the doc in the line of change
  • {timeout, Timeout::integer()}: timeout
  • heartbeat | {heartbeat, Heartbeat::integer()}: set couchdb to send a heartbeat to maintain connection open
  • {filter, FilterName} | {filter, FilterName, Args::list({key, value})}: set the filter to use with optional arguments
  • {view, ViewName}: use a view function as filter. Note that it requires to set filter special value "_view" to enable this feature.
  • >{stream_to, Pid}: the pid where the changes will be sent, by default the current pid. Used for continuous and longpoll connections

Return {ok, StartRef, ChangesPid} or {error, Error}. Ref can be used to disctint all changes from this pid. ChangesPid is the pid of the changes loop process. Can be used to monitor it or kill it when needed.

-
-
-
- -
- - - -
-

follow_once(Db)

- - - - - - -
-
- -
- -
- -
-spec follow_once(Db :: db()) -> {ok, LastSeq :: integer(), Changes :: list()} | {error, term()}.
- -
- - -
-
-
- -
- - - -
-

follow_once(Db, Options)

- - - - - - -
-
- -
- -
- -
-spec follow_once(Db :: db(), Options :: changes_options()) ->
-                     {ok, LastSeq :: integer(), Changes :: list()} | {error, term()}.
- -
- -

fetch all changes at once using a normal or longpoll connections.

Db : a db record

Options :: changes_options() [
-     | longpoll
-     | normal
-     | include_docs
-     | {since, integer() | now}
-     | {timeout, integer()}
-     | heartbeat | {heartbeat, integer()}
-     | {filter, string()}
-     | {filter, string(), list({string(), string() | integer()})}
-     | {docids, list()))},
-     | {stream_to, pid()}
-     ]
  • longpoll | normal: set the type of changes feed to get
  • include_docs: if you want to include the doc in the line of change
  • {timeout, Timeout::integer()}: timeout
  • heartbeat | {heartbeat, Heartbeat::integer()}: set couchdb to send a heartbeat to maintain connection open
  • {filter, FilterName} | {filter, FilterName, Args::list({key, value}): set the filter to use with optional arguments
  • {view, ViewName}: use a view function as filter. Note that it requires to set filter special value "_view" to enable this feature.

Result: {ok, LastSeq::integer(), Rows::list()} or {error, LastSeq, Error}. LastSeq is the last sequence of changes.

-
-
-
- -
- - - -
-

stream_next(Ref)

- - - - - - -
-
- -
- - -
-
- -
-
- - -
-
-
- - - diff --git a/site/couchbeam_changes_stream.html b/site/couchbeam_changes_stream.html deleted file mode 100644 index 56731be0..00000000 --- a/site/couchbeam_changes_stream.html +++ /dev/null @@ -1,374 +0,0 @@ - - - - - - - - - - - couchbeam_changes_stream — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - -
-
-

- couchbeam_changes_stream - (couchbeam v2.0.0) - -

- - - - View Source - - -
- - -
- -
-

- - - - Summary -

- - -
- - -
-

- - - - Functions -

-
-
- -
- - - -
-

init_stream(Parent, Owner, StreamRef, Db, Options)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

maybe_continue(State)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

start_link(Owner, StreamRef, Db, Options)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

system_code_change(Misc, _, _, _)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

system_continue(_, _, _)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

system_terminate(Reason, _, _, State)

- - - - - - -
-
- -
- -
- -
-spec system_terminate(any(), _, _, _) -> no_return().
- -
- - -
-
-
- -
- - - -
-

wait_reconnect(State)

- - - - - - -
-
- -
- - -
-
- -
-
- - -
-
-
- - - diff --git a/site/couchbeam_changes_sup.html b/site/couchbeam_changes_sup.html deleted file mode 100644 index a6ce3923..00000000 --- a/site/couchbeam_changes_sup.html +++ /dev/null @@ -1,224 +0,0 @@ - - - - - - - - - - - couchbeam_changes_sup — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - -
-
-

- couchbeam_changes_sup - (couchbeam v2.0.0) - -

- - - - View Source - - -
- - -
- -
-

- - - - Summary -

-
-

- Functions -

- -
-
- init(_) - -
- -
- -
-
- start_link() - -
- -
- -
- -
- - -
-

- - - - Functions -

-
-
- -
- - - -
-

init(_)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

start_link()

- - - - - - -
-
- -
- -
- -
-spec start_link() -> {ok, pid()}.
- -
- - -
-
- -
-
- - -
-
-
- - - diff --git a/site/couchbeam_doc.html b/site/couchbeam_doc.html deleted file mode 100644 index 02f1b1b8..00000000 --- a/site/couchbeam_doc.html +++ /dev/null @@ -1,849 +0,0 @@ - - - - - - - - - - - couchbeam_doc — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - -
-
-

- couchbeam_doc - (couchbeam v2.0.0) - -

- - - - View Source - - -
- - -
- -
-

- - - - Summary -

-
-

- Types -

- -
-
- doc/0 - -
- -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
- -
-
- ejson_term/0 - -
- -
- -
-
-

- Functions -

- -
- - -

Deletes all entries associated with Key in json object.

- -
- -
- - -

extend a jsonobject by a property, list of property or another jsonobject

- -
- -
- - -

extend a jsonobject by key, value

- -
- -
-
- get_id(Doc) - -
- -

get document id.

- -
- -
- - -

get a tuple containing docucment id and revision.

- -
- -
-
- get_rev(Doc) - -
- -

get document revision.

- -
- -
- - -

Returns the value of a simple key/value property in json object Equivalent to get_value(Key, JsonObj, undefined).

- -
- -
- - -

Returns the value of a simple key/value property in json object function from erlang_couchdb

- -
- -
- - -

If document have been saved (revision is defined) return true, else, return false.

- -
- -
- - -

set a value for a key in jsonobj. If key exists it will be updated.

- -
- -
- - -

Returns the value of a simple key/value property in json object and deletes it form json object Equivalent to take_value(Key, JsonObj, undefined).

- -
- -
- - -

Returns the value of a simple key/value property in json object and deletes it from json object

- -
- -
- -
- - -
-

- - - - Types -

-
-
- -
- - - -
-

doc/0

- - - - - - -
-
- -
- -
- -
-type doc() :: ejson_object().
- -
- - -
-
-
- -
- - - -
-

ejson_array/0

- - - - - - -
-
- -
- -
- -
-type ejson_array() :: [ejson_term()].
- -
- - -
-
-
- -
- - - -
-

ejson_number/0

- - - - - - -
-
- -
- -
- -
-type ejson_number() :: float() | integer().
- -
- - -
-
-
- -
- - - -
-

ejson_object/0

- - - - - - -
-
- -
- -
- -
-type ejson_object() :: map().
- -
- - -
-
-
- -
- - - -
-

ejson_string/0

- - - - - - -
-
- -
- -
- -
-type ejson_string() :: binary().
- -
- - -
-
-
- -
- - - -
-

ejson_term/0

- - - - - - -
-
- -
- -
- -
-type ejson_term() ::
-          ejson_array() | ejson_object() | ejson_string() | ejson_number() | true | false | null.
- -
- - -
-
- -
-
- -
-

- - - - Functions -

-
-
- -
- - - -
-

delete_value(Key, JsonObj)

- - - - - - -
-
- -
- -
- -
-spec delete_value(binary() | list(), doc()) -> doc().
- -
- -

Deletes all entries associated with Key in json object.

-
-
-
- -
- - - -
-

extend(R, JsonObj)

- - - - - - -
-
- -
- -
- -
-spec extend(term(), doc()) -> doc().
- -
- -

extend a jsonobject by a property, list of property or another jsonobject

-
-
-
- -
- - - -
-

extend(Key, Value, JsonObj)

- - - - - - -
-
- -
- -
- -
-spec extend(binary(), ejson_term(), doc()) -> doc().
- -
- -

extend a jsonobject by key, value

-
-
-
- -
- - - -
-

get_id(Doc)

- - - - - - -
-
- -
- -
- -
-spec get_id(doc()) -> binary().
- -
- -

get document id.

-
-
-
- -
- - - -
-

get_idrev(Doc)

- - - - - - -
-
- -
- -
- -
-spec get_idrev(doc()) -> {binary(), binary()}.
- -
- -

get a tuple containing docucment id and revision.

-
-
-
- -
- - - -
-

get_rev(Doc)

- - - - - - -
-
- -
- -
- -
-spec get_rev(doc()) -> binary().
- -
- -

get document revision.

-
-
-
- -
- - - -
-

get_value(Key, JsonObj)

- - - - - - -
-
- -
- -
- -
-spec get_value(binary() | list(), doc()) -> term().
- -
- -

Returns the value of a simple key/value property in json object Equivalent to get_value(Key, JsonObj, undefined).

-
-
-
- -
- - - -
-

get_value(Key, JsonObj, Default)

- - - - - - -
-
- -
- -
- -
-spec get_value(binary() | list(), doc(), term()) -> term().
- -
- -

Returns the value of a simple key/value property in json object function from erlang_couchdb

-
-
-
- -
- - - -
-

is_saved(Doc)

- - - - - - -
-
- -
- -
- -
-spec is_saved(doc()) -> boolean().
- -
- -

If document have been saved (revision is defined) return true, else, return false.

-
-
-
- -
- - - -
-

set_value(Key, Value, JsonObj)

- - - - - - -
-
- -
- -
- -
-spec set_value(binary() | list(), term(), doc()) -> doc().
- -
- -

set a value for a key in jsonobj. If key exists it will be updated.

-
-
-
- -
- - - -
-

take_value(Key, JsonObj)

- - - - - - -
-
- -
- -
- -
-spec take_value(binary() | list(), doc()) -> {term(), doc()}.
- -
- -

Returns the value of a simple key/value property in json object and deletes it form json object Equivalent to take_value(Key, JsonObj, undefined).

-
-
-
- -
- - - -
-

take_value(Key, JsonObj, Default)

- - - - - - -
-
- -
- -
- -
-spec take_value(binary() | list(), doc(), term()) -> {term(), doc()}.
- -
- -

Returns the value of a simple key/value property in json object and deletes it from json object

-
-
- -
-
- - -
-
-
- - - diff --git a/site/couchbeam_ejson.html b/site/couchbeam_ejson.html deleted file mode 100644 index 799e4984..00000000 --- a/site/couchbeam_ejson.html +++ /dev/null @@ -1,499 +0,0 @@ - - - - - - - - - - - couchbeam_ejson — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - -
-
-

- couchbeam_ejson - (couchbeam v2.0.0) - -

- - - - View Source - - -
- - -
- -
-

- - - - Summary -

-
-

- Types -

- -
-
- ejson/0 - -
- -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
- -
-
- ejson_term/0 - -
- -
- -
-
-

- Functions -

- -
-
- decode(D) - -
- -

decode a binary to an EJSON term. Throw an exception if there is any error.

- -
- -
-
- encode(D) - -
- -

encode an erlang term to JSON. Throw an exception if there is any error.

- -
- -
- - -
- -
- -
- - -
-

- - - - Types -

-
-
- -
- - - -
-

ejson/0

- - - - - - -
-
- -
- -
- -
-type ejson() :: ejson_object() | ejson_array().
- -
- - -
-
-
- -
- - - -
-

ejson_array/0

- - - - - - -
-
- -
- -
- -
-type ejson_array() :: [ejson_term()].
- -
- - -
-
-
- -
- - - -
-

ejson_number/0

- - - - - - -
-
- -
- -
- -
-type ejson_number() :: float() | integer().
- -
- - -
-
-
- -
- - - -
-

ejson_object/0

- - - - - - -
-
- -
- -
- -
-type ejson_object() :: map().
- -
- - -
-
-
- -
- - - -
-

ejson_string/0

- - - - - - -
-
- -
- -
- -
-type ejson_string() :: binary().
- -
- - -
-
-
- -
- - - -
-

ejson_term/0

- - - - - - -
-
- -
- -
- -
-type ejson_term() ::
-          ejson_array() | ejson_object() | ejson_string() | ejson_number() | true | false | null.
- -
- - -
-
- -
-
- -
-

- - - - Functions -

-
-
- -
- - - -
-

decode(D)

- - - - - - -
-
- -
- -
- -
-spec decode(binary()) -> ejson().
- -
- -

decode a binary to an EJSON term. Throw an exception if there is any error.

-
-
-
- -
- - - -
-

encode(D)

- - - - - - -
-
- -
- -
- -
-spec encode(ejson()) -> binary().
- -
- -

encode an erlang term to JSON. Throw an exception if there is any error.

-
-
-
- -
- - - -
-

post_decode(Term)

- - - - - - -
-
- -
- - -
-
- -
-
- - -
-
-
- - - diff --git a/site/couchbeam_httpc.html b/site/couchbeam_httpc.html deleted file mode 100644 index 8c0a2e6b..00000000 --- a/site/couchbeam_httpc.html +++ /dev/null @@ -1,568 +0,0 @@ - - - - - - - - - - - couchbeam_httpc — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - -
-
-

- couchbeam_httpc - (couchbeam v2.0.0) - -

- - - - View Source - - -
- - -
- -
-

- - - - Summary -

-
-

- Types -

- -
-
- db/0 - -
- -
- -
-
- server/0 - -
- -
- -
-
-

- Functions -

- - - - - -
- - -
- -
-
- db_url(Db) - -
- -
- -
- - -
- -
- - -
- - - - - - - -
- - -

Asemble the server URL for the given client

- -
- -
- -
- - -
-

- - - - Types -

-
-
- -
- - - -
-

db/0

- - - - - - -
-
- -
- -
- -
-type db() :: #db{server :: server(), name :: binary(), options :: list()}.
- -
- - -
-
-
- -
- - - -
-

server/0

- - - - - - -
-
- -
- -
- -
-type server() :: #server{url :: term(), options :: list()}.
- -
- - -
-
- -
-
- -
-

- - - - Functions -

-
-
- -
- - - -
-

db_request(Method, Url, Headers, Body, Options)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

db_request(Method, Url, Headers, Body, Options, Expect)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

db_resp(Resp, Expect)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

db_url(Db)

- - - - - - -
-
- -
- -
- -
-spec db_url(db()) -> binary().
- -
- - -
-
-
- -
- - - -
-

doc_url(Db, DocId)

- - - - - - -
-
- -
- -
- -
-spec doc_url(db(), binary()) -> binary().
- -
- - -
-
-
- -
- - - -
-

json_body(Ref)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

make_headers(Method, Url, Headers, Options)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

maybe_oauth_header(Method, Url, Headers, Options)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

request(Method, Url, Headers, Body, Options)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

server_url(Server)

- - - - - - -
-
- -
- -
- -
-spec server_url(server()) -> binary().
- -
- -

Asemble the server URL for the given client

-
-
- -
-
- - -
-
-
- - - diff --git a/site/couchbeam_sup.html b/site/couchbeam_sup.html deleted file mode 100644 index bee7b056..00000000 --- a/site/couchbeam_sup.html +++ /dev/null @@ -1,218 +0,0 @@ - - - - - - - - - - - couchbeam_sup — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - -
-
-

- couchbeam_sup - (couchbeam v2.0.0) - -

- - - - View Source - - -
- - -
- -
-

- - - - Summary -

-
-

- Functions -

- -
-
- init(_) - -
- -
- -
-
- start_link() - -
- -
- -
- -
- - -
-

- - - - Functions -

-
-
- -
- - - -
-

init(_)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

start_link()

- - - - - - -
-
- -
- - -
-
- -
-
- - -
-
-
- - - diff --git a/site/couchbeam_util.html b/site/couchbeam_util.html deleted file mode 100644 index 712b29be..00000000 --- a/site/couchbeam_util.html +++ /dev/null @@ -1,972 +0,0 @@ - - - - - - - - - - - couchbeam_util — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - -
-
-

- couchbeam_util - (couchbeam v2.0.0) - -

- - - - View Source - - -
- - -
- -
-

- - - - Summary -

-
-

- Functions -

- - - -
- - -
- - - -
- - -
- -
- - -
- -
- - -
- - - -
- - -

Encode needed query parameter values for JSON

- -
- -
- - -

Encode value in JSON if needed depending on the key

- -
- -
- - -

Replace a value in a property list

- -
- - - -
- - -

Emulate proplists:get_value/2,3 for property lists but use faster lists:keyfind/3

- -
- - - - - -
- - -

make view options a list

- -
- - - -
- - -

Update a property list with values of the second. In case the same key is in both lists, the value from the first is kept.

- -
- -
- - -

Merge two property lists (lists of {Key,Value}). All the Key - Value pairs from both lists are included in the new list. If a key occurs in both dictionaries then Fun is called with the key and both values to return a new value. This a wreapper around dict:merge

- -
- - - - - -
- - -
- -
- - -

Start depedent applications of App.

- -
- -
-
- to_atom(V) - -
- -
- -
-
- to_binary(V) - -
- -
- -
- - -
- -
-
- to_list(V) - -
- -
- -
- -
- - -
-

- - - - Functions -

-
-
- -
- - - -
-

binary_env(Key, Default)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

dbname(DbName)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

deprecated(Old, New, When)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

encode_att_name(Name)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

encode_docid1(DocId)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

encode_docid(DocId)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

encode_docid_noop(DocId)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

encode_query(QSL)

- - - - - - -
-
- -
- -

Encode needed query parameter values for JSON

-
-
-
- -
- - - -
-

encode_query_value(K, V)

- - - - - - -
-
- -
- -

Encode value in JSON if needed depending on the key

-
-
-
- -
- - - -
-

force_param(Key, Value, Options)

- - - - - - -
-
- -
- -

Replace a value in a property list

-
-
-
- -
- - - -
-

get_app_env(Env, Default)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

get_value(Key, Prop)

- - - - - - -
-
- -
- -
- -
-spec get_value(Key :: term(), Prop :: [term()]) -> term().
- -
- -

Emulate proplists:get_value/2,3 for property lists but use faster lists:keyfind/3

-
-
-
- -
- - - -
-

get_value(Key, Prop, Default)

- - - - - - -
-
- -
- -
- -
-spec get_value(Key :: term(), Prop :: [term()], Default :: term()) -> term().
- -
- - -
-
-
- -
- - - -
-

oauth_header(Url, Action, OauthProps)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

parse_options(Options)

- - - - - - -
-
- -
- -

make view options a list

-
-
-
- -
- - - -
-

parse_options(Rest, Acc)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

propmerge1(L1, L2)

- - - - - - -
-
- -
- -

Update a property list with values of the second. In case the same key is in both lists, the value from the first is kept.

-
-
-
- -
- - - -
-

propmerge(F, L1, L2)

- - - - - - -
-
- -
- -

Merge two property lists (lists of {Key,Value}). All the Key - Value pairs from both lists are included in the new list. If a key occurs in both dictionaries then Fun is called with the key and both values to return a new value. This a wreapper around dict:merge

-
-
-
- -
- - - -
-

proxy_header(UserName, Roles, Secret)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

proxy_token(Secret, UserName)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

shutdown_sync(Pid)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

start_app_deps(App)

- - - - - - -
-
- -
- -
- -
-spec start_app_deps(atom()) -> ok.
- -
- -

Start depedent applications of App.

-
-
-
- -
- - - -
-

to_atom(V)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

to_binary(V)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

to_integer(V)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

to_list(V)

- - - - - - -
-
- -
- - -
-
- -
-
- - -
-
-
- - - diff --git a/site/couchbeam_uuids.html b/site/couchbeam_uuids.html deleted file mode 100644 index 64efa5e0..00000000 --- a/site/couchbeam_uuids.html +++ /dev/null @@ -1,544 +0,0 @@ - - - - - - - - - - - couchbeam_uuids — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - -
-
-

- couchbeam_uuids - (couchbeam v2.0.0) - -

- - - - View Source - - -
- - -
- -
-

- - - - Summary -

-
-

- Types -

- -
-
- server/0 - -
- -
- -
-
-

- Functions -

- - - -
- - -

Get a list of uuids from the server

- -
- - - - - - - -
-
- init(_) - -
- -
- -
-
- random() - -
- -

return a random uuid

- -
- -
-
- start_link() - -
- -

Starts the couchbeam process linked to the calling process. Usually invoked by the supervisor couchbeam_sup

- -
- - - -
-
- utc_random() - -
- -

return a random uuid based on time

- -
- -
- -
- - -
-

- - - - Types -

-
-
- -
- - - -
-

server/0

- - - - - - -
-
- -
- -
- -
-type server() :: #server{url :: term(), options :: list()}.
- -
- - -
-
- -
-
- -
-

- - - - Functions -

-
-
- -
- - - -
-

code_change(OldVsn, State, Extra)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

get_uuids(Server, Count)

- - - - - - -
-
- -
- -
- -
-spec get_uuids(server(), integer()) -> list().
- -
- -

Get a list of uuids from the server

-
-
-
- -
- - - -
-

handle_call(_, From, State)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

handle_cast(Msg, State)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

handle_info(Info, State)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

init(_)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

random()

- - - - - - -
-
- -
- -
- -
-spec random() -> binary().
- -
- -

return a random uuid

-
-
-
- -
- - - -
-

start_link()

- - - - - - -
-
- -
- -
- -
-spec start_link() -> {ok, pid()} | {error, term()}.
- -
- -

Starts the couchbeam process linked to the calling process. Usually invoked by the supervisor couchbeam_sup

-
-
-
- -
- - - -
-

terminate(Reason, State)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

utc_random()

- - - - - - -
-
- -
- -
- -
-spec utc_random() -> binary().
- -
- -

return a random uuid based on time

-
-
- -
-
- - -
-
-
- - - diff --git a/site/couchbeam_view.html b/site/couchbeam_view.html deleted file mode 100644 index 474e0820..00000000 --- a/site/couchbeam_view.html +++ /dev/null @@ -1,1508 +0,0 @@ - - - - - - - - - - - couchbeam_view — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - -
-
-

- couchbeam_view - (couchbeam v2.0.0) - -

- - - - View Source - - -
- - -
- -
-

- - - - Summary -

-
-

- Types -

- -
-
- db/0 - -
- -
- -
- - -
- -
- - -
- -
-
- server/0 - -
- -
- -
- - -

example: "foo=bar&baz=biz"

- -
- -
- - -
- -
-
- stale/0 - -
- -
- -
-
- view_name/0 - -
- -
- -
- - -
- -
- - -
- -
- - -
- -
-
-

- Functions -

- -
-
- all(Db) - -
- - - -
- -
- - - - -
- -
- - -
- -
-
- count(Db) - -
- - - -
- -
- - - - -
- -
- - -

count number of doc in a view (or all docs)

- -
- -
-
- fetch(Db) - -
- - - -
- -
- - - - -
- -
- - -

Collect view results

- -
- -
-
- first(Db) - -
- -
- -
- - - - -
- -
- - -

get first result of a view

- -
- - - -
- - -

call Function(Row, AccIn) on succesive row, starting with AccIn == Acc. Function/2 must return a new list accumultator or the atom done to stop fetching results. Acc0 is returned if the list is empty. For example

- -
- - - -
- - -

call Function(Row) on succesive row. Example

- -
- -
- - -

parse view options

- -
- -
- - -
- - - - - -
- - - - -
- -
- - -

stream view results to a pid Db: a db record ViewName: 'all_docs' to get all docs or {DesignName, ViewName} Client receives messages: - {row, StartRef, done} All rows have been fetched - {row, StartRef, Row :: ejson_object()} A row in the view - {error, StartRef, Error} An error occurred; stream closed Options include (see couchbeam_view:parse_view_options/1): - {key, Key} - {start_docid, DocId} | {startkey_docid, DocId} - {end_docid, DocId} | {endkey_docid, DocId} - {start_key, Key} | {end_key, Key} - {limit, N} - {stale, ok | update_after | false} - descending | {skip, N} - group | {group_level, integer()} - reduce | {reduce, boolean()} - include_docs | conflicts | {inclusive_end, boolean()} - {keys, [Key]} - {stream_to, Pid}

- -
- -
- - -
- -
- -
- - -
-

- - - - Types -

-
-
- -
- - - -
-

db/0

- - - - - - -
-
- -
- -
- -
-type db() :: #db{server :: server(), name :: binary(), options :: list()}.
- -
- - -
-
-
- -
- - - -
-

design_name/0

- - - - - - -
-
- -
- -
- -
-type design_name() :: binary() | string().
- -
- - -
-
-
- -
- - - -
-

ejson_object/0

- - - - - - -
-
- -
- -
- -
-type ejson_object() :: map().
- -
- - -
-
-
- -
- - - -
-

server/0

- - - - - - -
-
- -
- -
- -
-type server() :: #server{url :: term(), options :: list()}.
- -
- - -
-
-
- -
- - - -
-

show_option/0

- - - - - - -
-
- -
- -
- -
-type show_option() :: {query_string, binary()}.
- -
- -

example: "foo=bar&baz=biz"

-
-
-
- -
- - - -
-

show_options/0

- - - - - - -
-
- -
- -
- -
-type show_options() :: [show_option()].
- -
- - -
-
-
- -
- - - -
-

stale/0

- - - - - - -
-
- -
- -
- -
-type stale() :: ok | update_after | false.
- -
- - -
-
-
- -
- - - -
-

view_name/0

- - - - - - -
-
- -
- -
- -
-type view_name() :: binary() | string().
- -
- - -
-
-
- -
- - - -
-

view_option/0

- - - - - - -
-
- -
- -
- -
-type view_option() ::
-          {key, binary()} |
-          {startkey_docid, binary()} |
-          {start_docid, binary()} |
-          {startkey_docid, binary()} |
-          {end_docid, binary()} |
-          {endkey_docid, binary()} |
-          {start_key, binary()} |
-          {end_key, binary()} |
-          {limit, integer()} |
-          {stale, stale()} |
-          descending |
-          {skip, integer()} |
-          group |
-          {group_level, exact | integer()} |
-          reduce |
-          {reduce, boolean()} |
-          inclusive_end | include_docs | conflicts |
-          {list, binary()} |
-          {keys, [binary()]} |
-          async_query.
- -
- - -
-
-
- -
- - - -
-

view_options/0

- - - - - - -
-
- -
- -
- -
-type view_options() :: [view_option()].
- -
- - -
-
-
- -
- - - -
-

view_query_args/0

- - - - - - -
-
- -
- -
- -
-type view_query_args() ::
-          #view_query_args{method :: atom(), options :: view_options(), keys :: [binary()]}.
- -
- - -
-
- -
-
- -
-

- - - - Functions -

-
-
- -
- - - -
-

all(Db)

- - - - - - -
-
- -
- -
- -
-spec all(Db :: db()) ->
-             {ok, Rows :: [ejson_object()]} |
-             {error, term()} |
-             {error, term(), Rows :: [ejson_object()]}.
- -
- -

Equivalent to fetch(Db, all_docs, []).

fetch all docs

-
-
-
- -
- - - -
-

all(Db, Options)

- - - - - - -
-
- -
- -
- -
-spec all(Db :: db(), Options :: view_options()) ->
-             {ok, Rows :: [ejson_object()]} |
-             {error, term()} |
-             {error, term(), Rows :: [ejson_object()]}.
- -
- -

Equivalent to fetch(Db, all_docs, Options).

fetch all docs

-
-
-
- -
- - - -
-

cancel_stream(Ref)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

count(Db)

- - - - - - -
-
- -
- -
- -
-spec count(Db :: db()) -> integer() | {error, term()}.
- -
- -

Equivalent to count(Db, all_docs, []).

-
-
-
- -
- - - -
-

count(Db, ViewName)

- - - - - - -
-
- -
- -
- -
-spec count(Db :: db(), ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()}) ->
-               integer() | {error, term()}.
- -
- -

Equivalent to count(Db, ViewName, []).

-
-
-
- -
- - - -
-

count(Db, ViewName, Options)

- - - - - - -
-
- -
- -
- -
-spec count(Db :: db(),
-            ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()},
-            Options :: view_options()) ->
-               integer() | {error, term()}.
- -
- -

count number of doc in a view (or all docs)

-
-
-
- -
- - - -
-

fetch(Db)

- - - - - - -
-
- -
- -
- -
-spec fetch(Db :: db()) ->
-               {ok, Rows :: [ejson_object()]} |
-               {error, term()} |
-               {error, term(), Rows :: [ejson_object()]}.
- -
- -

Equivalent to fetch(Db, all_docs, []).

-
-
-
- -
- - - -
-

fetch(Db, ViewName)

- - - - - - -
-
- -
- -
- -
-spec fetch(Db :: db(), ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()}) ->
-               {ok, Rows :: [ejson_object()]} | {error, term()}.
- -
- -

Equivalent to fetch(Db, ViewName, []).

-
-
-
- -
- - - -
-

fetch(Db, ViewName, Options)

- - - - - - -
-
- -
- -
- -
-spec fetch(Db :: db(),
-            ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()},
-            Options :: view_options()) ->
-               {ok, Rows :: [ejson_object()]} | {error, term()}.
- -
- -

Collect view results

Db: a db record

ViewName: 'all_docs' to get all docs or {DesignName, ViewName}

Options :: view_options() [{key, binary()}
-     | {start_docid, binary()} | {startkey_docid, binary()}
-     | {end_docid, binary()} | {endkey_docid, binary()}
-     | {start_key, binary()} | {end_key, binary()}
-     | {limit, integer()}
-     | {stale, stale()}
-     | descending
-     | {skip, integer()}
-     | group | {group_level, integer()}
-     | {inclusive_end, boolean()} | {reduce, boolean()} | reduce | include_docs | conflicts
-     | {keys, list(binary())}
-     | async_query

See couchbeam_view:stream/3 for more information about options.

Return: {ok, Rows} or {error, Error}

-
-
-
- -
- - - -
-

first(Db)

- - - - - - -
-
- -
- -
- -
-spec first(Db :: db()) -> {ok, Row :: ejson_object()} | {error, term()}.
- -
- - -
-
-
- -
- - - -
-

first(Db, ViewName)

- - - - - - -
-
- -
- -
- -
-spec first(Db :: db(), ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()}) ->
-               {ok, Row :: ejson_object()} | {error, term()}.
- -
- -

Equivalent to first(Db, ViewName, []).

-
-
-
- -
- - - -
-

first(Db, ViewName, Options)

- - - - - - -
-
- -
- -
- -
-spec first(Db :: db(),
-            ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()},
-            Options :: view_options()) ->
-               {ok, Rows :: ejson_object()} | {error, term()}.
- -
- -

get first result of a view

Db: a db record

ViewName: 'all_docs' to get all docs or {DesignName, ViewName}

Options :: view_options() [{key, binary()}
-     | {start_docid, binary()} | {startkey_docid, binary()}
-     | {end_docid, binary()} | {endkey_docid, binary()}
-     | {start_key, binary()} | {end_key, binary()}
-     | {limit, integer()}
-     | {stale, stale()}
-     | descending
-     | {skip, integer()}
-     | group | {group_level, integer()}
-     | {inclusive_end, boolean()} | {reduce, boolean()} | reduce | include_docs | conflicts
-     | {keys, list(binary())}

See couchbeam_view:stream/3 for more information about options.

Return: {ok, Row} or {error, Error}

-
-
-
- -
- - - -
-

fold(Function, Acc, Db, ViewName)

- - - - - - -
-
- -
- -
- -
-spec fold(Function :: function(),
-           Acc :: any(),
-           Db :: db(),
-           ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()}) ->
-              [term()] | {error, term()}.
- -
- -

Equivalent to fold(Function, Acc, Db, ViewName, []).

-
-
-
- -
- - - -
-

fold(Function, Acc, Db, ViewName, Options)

- - - - - - -
-
- -
- -
- -
-spec fold(Function :: function(),
-           Acc :: any(),
-           Db :: db(),
-           ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()},
-           Options :: view_options()) ->
-              [term()] | {error, term()}.
- -
- -

call Function(Row, AccIn) on succesive row, starting with AccIn == Acc. Function/2 must return a new list accumultator or the atom done to stop fetching results. Acc0 is returned if the list is empty. For example:

  couchbeam_view:fold(fun(Row, Acc) -> [Row|Acc] end, [], Db, 'all_docs').
-
-
-
- -
- - - -
-

foreach(Function, Db, ViewName)

- - - - - - -
-
- -
- -
- -
-spec foreach(Function :: function(),
-              Db :: db(),
-              ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()}) ->
-                 [term()] | {error, term()}.
- -
- -

Equivalent to foreach(Function, Db, ViewName, []).

-
-
-
- -
- - - -
-

foreach(Function, Db, ViewName, Options)

- - - - - - -
-
- -
- -
- -
-spec foreach(Function :: function(),
-              Db :: db(),
-              ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()},
-              Options :: view_options()) ->
-                 [term()] | {error, term()}.
- -
- -

call Function(Row) on succesive row. Example:

  couchbeam_view:foreach(fun(Row) -> io:format("got row ~p~n", [Row]) end, Db, 'all_docs').
-
-
-
- -
- - - -
-

parse_view_options(Options)

- - - - - - -
-
- -
- -
- -
-spec parse_view_options(Options :: list()) -> view_query_args().
- -
- -

parse view options

-
-
-
- -
- - - -
-

show(Db, ShowName)

- - - - - - -
-
- -
- -
- -
-spec show(db(), {binary(), binary()}) -> {ok, ejson_object()} | {error, term()}.
- -
- - -
-
-
- -
- - - -
-

show(Db, ShowName, DocId)

- - - - - - -
-
- -
- -
- -
-spec show(db(), {binary(), binary()}, binary()) -> {ok, ejson_object()} | {error, term()}.
- -
- - -
-
-
- -
- - - -
-

show(Db, _, DocId, Options)

- - - - - - -
-
- -
- -
- -
-spec show(db(), {binary(), binary()}, null | binary(), show_options()) ->
-              {ok, ejson_object()} | {error, term()}.
- -
- - -
-
-
- -
- - - -
-

stream(Db, ViewName)

- - - - - - -
-
- -
- -
- -
-spec stream(Db :: db(), ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()}) ->
-                {ok, StartRef :: term(), ViewPid :: pid()} | {error, term()}.
- -
- -

Equivalent to stream(Db, ViewName, []).

-
-
-
- -
- - - -
-

stream(Db, ViewName, Options)

- - - - - - -
-
- -
- -
- -
-spec stream(Db :: db(),
-             ViewName :: all_docs | {DesignName :: design_name(), ViewName :: view_name()},
-             Options :: view_options()) ->
-                {ok, StartRef :: term()} | {error, term()}.
- -
- -

stream view results to a pid Db: a db record ViewName: 'all_docs' to get all docs or {DesignName, ViewName} Client receives messages: - {row, StartRef, done} All rows have been fetched - {row, StartRef, Row :: ejson_object()} A row in the view - {error, StartRef, Error} An error occurred; stream closed Options include (see couchbeam_view:parse_view_options/1): - {key, Key} - {start_docid, DocId} | {startkey_docid, DocId} - {end_docid, DocId} | {endkey_docid, DocId} - {start_key, Key} | {end_key, Key} - {limit, N} - {stale, ok | update_after | false} - descending | {skip, N} - group | {group_level, integer()} - reduce | {reduce, boolean()} - include_docs | conflicts | {inclusive_end, boolean()} - {keys, [Key]} - {stream_to, Pid}

-
-
-
- -
- - - -
-

stream_next(Ref)

- - - - - - -
-
- -
- - -
-
- -
-
- - -
-
-
- - - diff --git a/site/couchbeam_view_stream.html b/site/couchbeam_view_stream.html deleted file mode 100644 index 8342df91..00000000 --- a/site/couchbeam_view_stream.html +++ /dev/null @@ -1,344 +0,0 @@ - - - - - - - - - - - couchbeam_view_stream — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - -
-
-

- couchbeam_view_stream - (couchbeam v2.0.0) - -

- - - - View Source - - -
- - -
- -
-

- - - - Summary -

- - -
- - -
-

- - - - Functions -

-
-
- -
- - - -
-

init_stream(Parent, Owner, StreamRef, Req, StreamOptions)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

maybe_continue(State)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

start_link(Owner, StreamRef, _, StreamOptions)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

system_code_change(Misc, _, _, _)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

system_continue(_, _, _)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

system_terminate(Reason, _, _, State)

- - - - - - -
-
- -
- -
- -
-spec system_terminate(any(), _, _, _) -> no_return().
- -
- - -
-
- -
-
- - -
-
-
- - - diff --git a/site/couchbeam_view_sup.html b/site/couchbeam_view_sup.html deleted file mode 100644 index fe1415e0..00000000 --- a/site/couchbeam_view_sup.html +++ /dev/null @@ -1,224 +0,0 @@ - - - - - - - - - - - couchbeam_view_sup — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - -
-
-

- couchbeam_view_sup - (couchbeam v2.0.0) - -

- - - - View Source - - -
- - -
- -
-

- - - - Summary -

-
-

- Functions -

- -
-
- init(_) - -
- -
- -
-
- start_link() - -
- -
- -
- -
- - -
-

- - - - Functions -

-
-
- -
- - - -
-

init(_)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

start_link()

- - - - - - -
-
- -
- -
- -
-spec start_link() -> {ok, pid()}.
- -
- - -
-
- -
-
- - -
-
-
- - - diff --git a/site/dist/html-DPJLHKSM.js b/site/dist/html-DPJLHKSM.js deleted file mode 100644 index 8d3e3097..00000000 --- a/site/dist/html-DPJLHKSM.js +++ /dev/null @@ -1,222 +0,0 @@ -(()=>{var Ps=Object.create;var Kn=Object.defineProperty;var Os=Object.getOwnPropertyDescriptor;var Is=Object.getOwnPropertyNames;var As=Object.getPrototypeOf,Cs=Object.prototype.hasOwnProperty;var L=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var Rs=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Is(e))!Cs.call(t,i)&&i!==n&&Kn(t,i,{get:()=>e[i],enumerable:!(r=Os(e,i))||r.enumerable});return t};var Y=(t,e,n)=>(n=t!=null?Ps(As(t)):{},Rs(e||!t||!t.__esModule?Kn(n,"default",{value:t,enumerable:!0}):n,t));var wr=L((cc,yr)=>{var vr="Expected a function",mr=NaN,Bs="[object Symbol]",Qs=/^\s+|\s+$/g,qs=/^[-+]0x[0-9a-f]+$/i,Fs=/^0b[01]+$/i,Vs=/^0o[0-7]+$/i,$s=parseInt,Us=typeof global=="object"&&global&&global.Object===Object&&global,js=typeof self=="object"&&self&&self.Object===Object&&self,Ws=Us||js||Function("return this")(),zs=Object.prototype,Gs=zs.toString,Ks=Math.max,Ys=Math.min,Bt=function(){return Ws.Date.now()};function Js(t,e,n){var r,i,s,o,a,l,u=0,c=!1,d=!1,h=!0;if(typeof t!="function")throw new TypeError(vr);e=gr(e)||0,Fe(n)&&(c=!!n.leading,d="maxWait"in n,s=d?Ks(gr(n.maxWait)||0,e):s,h="trailing"in n?!!n.trailing:h);function p(S){var R=r,U=i;return r=i=void 0,u=S,o=t.apply(U,R),o}function g(S){return u=S,a=setTimeout(w,e),c?p(S):o}function m(S){var R=S-l,U=S-u,ee=e-R;return d?Ys(ee,s-U):ee}function v(S){var R=S-l,U=S-u;return l===void 0||R>=e||R<0||d&&U>=s}function w(){var S=Bt();if(v(S))return x(S);a=setTimeout(w,m(S))}function x(S){return a=void 0,h&&r?p(S):(r=i=void 0,o)}function P(){a!==void 0&&clearTimeout(a),u=0,r=l=i=a=void 0}function q(){return a===void 0?o:x(Bt())}function $(){var S=Bt(),R=v(S);if(r=arguments,i=this,l=S,R){if(a===void 0)return g(l);if(d)return a=setTimeout(w,e),p(l)}return a===void 0&&(a=setTimeout(w,e)),o}return $.cancel=P,$.flush=q,$}function Xs(t,e,n){var r=!0,i=!0;if(typeof t!="function")throw new TypeError(vr);return Fe(n)&&(r="leading"in n?!!n.leading:r,i="trailing"in n?!!n.trailing:i),Js(t,e,{leading:r,maxWait:e,trailing:i})}function Fe(t){var e=typeof t;return!!t&&(e=="object"||e=="function")}function Zs(t){return!!t&&typeof t=="object"}function eo(t){return typeof t=="symbol"||Zs(t)&&Gs.call(t)==Bs}function gr(t){if(typeof t=="number")return t;if(eo(t))return mr;if(Fe(t)){var e=typeof t.valueOf=="function"?t.valueOf():t;t=Fe(e)?e+"":e}if(typeof t!="string")return t===0?t:+t;t=t.replace(Qs,"");var n=Fs.test(t);return n||Vs.test(t)?$s(t.slice(2),n?2:8):qs.test(t)?mr:+t}yr.exports=Xs});var F=L(D=>{"use strict";D.__esModule=!0;D.extend=Cr;D.indexOf=po;D.escapeExpression=mo;D.isEmpty=go;D.createFrame=vo;D.blockParams=yo;D.appendContextPath=wo;var uo={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`","=":"="},co=/[&<>"'`=]/g,ho=/[&<>"'`=]/;function fo(t){return uo[t]}function Cr(t){for(var e=1;e{"use strict";je.__esModule=!0;var Kt=["description","fileName","lineNumber","endLineNumber","message","name","number","stack"];function Yt(t,e){var n=e&&e.loc,r=void 0,i=void 0,s=void 0,o=void 0;n&&(r=n.start.line,i=n.end.line,s=n.start.column,o=n.end.column,t+=" - "+r+":"+s);for(var a=Error.prototype.constructor.call(this,t),l=0;l{"use strict";We.__esModule=!0;var Jt=F();We.default=function(t){t.registerHelper("blockHelperMissing",function(e,n){var r=n.inverse,i=n.fn;if(e===!0)return i(this);if(e===!1||e==null)return r(this);if(Jt.isArray(e))return e.length>0?(n.ids&&(n.ids=[n.name]),t.helpers.each(e,n)):r(this);if(n.data&&n.ids){var s=Jt.createFrame(n.data);s.contextPath=Jt.appendContextPath(n.data.contextPath,n.name),n={data:s}}return i(e,n)})};Hr.exports=We.default});var Br=L((ze,Dr)=>{"use strict";ze.__esModule=!0;function bo(t){return t&&t.__esModule?t:{default:t}}var we=F(),Eo=X(),xo=bo(Eo);ze.default=function(t){t.registerHelper("each",function(e,n){if(!n)throw new xo.default("Must pass iterator to #each");var r=n.fn,i=n.inverse,s=0,o="",a=void 0,l=void 0;n.data&&n.ids&&(l=we.appendContextPath(n.data.contextPath,n.ids[0])+"."),we.isFunction(e)&&(e=e.call(this)),n.data&&(a=we.createFrame(n.data));function u(g,m,v){a&&(a.key=g,a.index=m,a.first=m===0,a.last=!!v,l&&(a.contextPath=l+g)),o=o+r(e[g],{data:a,blockParams:we.blockParams([e[g],g],[l+g,null])})}if(e&&typeof e=="object")if(we.isArray(e))for(var c=e.length;s{"use strict";Ge.__esModule=!0;function ko(t){return t&&t.__esModule?t:{default:t}}var So=X(),Lo=ko(So);Ge.default=function(t){t.registerHelper("helperMissing",function(){if(arguments.length!==1)throw new Lo.default('Missing helper: "'+arguments[arguments.length-1].name+'"')})};Qr.exports=Ge.default});var Ur=L((Ke,$r)=>{"use strict";Ke.__esModule=!0;function To(t){return t&&t.__esModule?t:{default:t}}var Fr=F(),_o=X(),Vr=To(_o);Ke.default=function(t){t.registerHelper("if",function(e,n){if(arguments.length!=2)throw new Vr.default("#if requires exactly one argument");return Fr.isFunction(e)&&(e=e.call(this)),!n.hash.includeZero&&!e||Fr.isEmpty(e)?n.inverse(this):n.fn(this)}),t.registerHelper("unless",function(e,n){if(arguments.length!=2)throw new Vr.default("#unless requires exactly one argument");return t.helpers.if.call(this,e,{fn:n.inverse,inverse:n.fn,hash:n.hash})})};$r.exports=Ke.default});var Wr=L((Ye,jr)=>{"use strict";Ye.__esModule=!0;Ye.default=function(t){t.registerHelper("log",function(){for(var e=[void 0],n=arguments[arguments.length-1],r=0;r{"use strict";Je.__esModule=!0;Je.default=function(t){t.registerHelper("lookup",function(e,n,r){return e&&r.lookupProperty(e,n)})};zr.exports=Je.default});var Yr=L((Xe,Kr)=>{"use strict";Xe.__esModule=!0;function Po(t){return t&&t.__esModule?t:{default:t}}var be=F(),Oo=X(),Io=Po(Oo);Xe.default=function(t){t.registerHelper("with",function(e,n){if(arguments.length!=2)throw new Io.default("#with requires exactly one argument");be.isFunction(e)&&(e=e.call(this));var r=n.fn;if(be.isEmpty(e))return n.inverse(this);var i=n.data;return n.data&&n.ids&&(i=be.createFrame(n.data),i.contextPath=be.appendContextPath(n.data.contextPath,n.ids[0])),r(e,{data:i,blockParams:be.blockParams([e],[i&&i.contextPath])})})};Kr.exports=Xe.default});var Xt=L(Ze=>{"use strict";Ze.__esModule=!0;Ze.registerDefaultHelpers=jo;Ze.moveHelperToHooks=Wo;function se(t){return t&&t.__esModule?t:{default:t}}var Ao=Nr(),Co=se(Ao),Ro=Br(),Mo=se(Ro),Ho=qr(),No=se(Ho),Do=Ur(),Bo=se(Do),Qo=Wr(),qo=se(Qo),Fo=Gr(),Vo=se(Fo),$o=Yr(),Uo=se($o);function jo(t){Co.default(t),Mo.default(t),No.default(t),Bo.default(t),qo.default(t),Vo.default(t),Uo.default(t)}function Wo(t,e,n){t.helpers[e]&&(t.hooks[e]=t.helpers[e],n||delete t.helpers[e])}});var Xr=L((et,Jr)=>{"use strict";et.__esModule=!0;var zo=F();et.default=function(t){t.registerDecorator("inline",function(e,n,r,i){var s=e;return n.partials||(n.partials={},s=function(o,a){var l=r.partials;r.partials=zo.extend({},l,n.partials);var u=e(o,a);return r.partials=l,u}),n.partials[i.args[0]]=i.fn,s})};Jr.exports=et.default});var Zr=L(Zt=>{"use strict";Zt.__esModule=!0;Zt.registerDefaultDecorators=Jo;function Go(t){return t&&t.__esModule?t:{default:t}}var Ko=Xr(),Yo=Go(Ko);function Jo(t){Yo.default(t)}});var en=L((tt,ei)=>{"use strict";tt.__esModule=!0;var Xo=F(),fe={methodMap:["debug","info","warn","error"],level:"info",lookupLevel:function(e){if(typeof e=="string"){var n=Xo.indexOf(fe.methodMap,e.toLowerCase());n>=0?e=n:e=parseInt(e,10)}return e},log:function(e){if(e=fe.lookupLevel(e),typeof console<"u"&&fe.lookupLevel(fe.level)<=e){var n=fe.methodMap[e];console[n]||(n="log");for(var r=arguments.length,i=Array(r>1?r-1:0),s=1;s{"use strict";tn.__esModule=!0;tn.createNewLookupObject=ea;var Zo=F();function ea(){for(var t=arguments.length,e=Array(t),n=0;n{"use strict";Ee.__esModule=!0;Ee.createProtoAccessControl=ia;Ee.resultIsAllowed=sa;Ee.resetLoggedProperties=aa;function ta(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e.default=t,e}var ni=ti(),na=en(),ra=ta(na),nt=Object.create(null);function ia(t){var e=Object.create(null);e.constructor=!1,e.__defineGetter__=!1,e.__defineSetter__=!1,e.__lookupGetter__=!1;var n=Object.create(null);return n.__proto__=!1,{properties:{whitelist:ni.createNewLookupObject(n,t.allowedProtoProperties),defaultValue:t.allowProtoPropertiesByDefault},methods:{whitelist:ni.createNewLookupObject(e,t.allowedProtoMethods),defaultValue:t.allowProtoMethodsByDefault}}}function sa(t,e,n){return ri(typeof t=="function"?e.methods:e.properties,n)}function ri(t,e){return t.whitelist[e]!==void 0?t.whitelist[e]===!0:t.defaultValue!==void 0?t.defaultValue:(oa(e),!1)}function oa(t){nt[t]!==!0&&(nt[t]=!0,ra.log("error",'Handlebars: Access has been denied to resolve the property "'+t+`" because it is not an "own property" of its parent. -You can add a runtime option to disable the check or this warning: -See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details`))}function aa(){Object.keys(nt).forEach(function(t){delete nt[t]})}});var an=L(j=>{"use strict";j.__esModule=!0;j.HandlebarsEnvironment=on;function ii(t){return t&&t.__esModule?t:{default:t}}var oe=F(),la=X(),rn=ii(la),ua=Xt(),ca=Zr(),da=en(),rt=ii(da),ha=nn(),fa="4.7.7";j.VERSION=fa;var pa=8;j.COMPILER_REVISION=pa;var ma=7;j.LAST_COMPATIBLE_COMPILER_REVISION=ma;var ga={1:"<= 1.0.rc.2",2:"== 1.0.0-rc.3",3:"== 1.0.0-rc.4",4:"== 1.x.x",5:"== 2.0.0-alpha.x",6:">= 2.0.0-beta.1",7:">= 4.0.0 <4.3.0",8:">= 4.3.0"};j.REVISION_CHANGES=ga;var sn="[object Object]";function on(t,e,n){this.helpers=t||{},this.partials=e||{},this.decorators=n||{},ua.registerDefaultHelpers(this),ca.registerDefaultDecorators(this)}on.prototype={constructor:on,logger:rt.default,log:rt.default.log,registerHelper:function(e,n){if(oe.toString.call(e)===sn){if(n)throw new rn.default("Arg not supported with multiple helpers");oe.extend(this.helpers,e)}else this.helpers[e]=n},unregisterHelper:function(e){delete this.helpers[e]},registerPartial:function(e,n){if(oe.toString.call(e)===sn)oe.extend(this.partials,e);else{if(typeof n>"u")throw new rn.default('Attempting to register a partial called "'+e+'" as undefined');this.partials[e]=n}},unregisterPartial:function(e){delete this.partials[e]},registerDecorator:function(e,n){if(oe.toString.call(e)===sn){if(n)throw new rn.default("Arg not supported with multiple decorators");oe.extend(this.decorators,e)}else this.decorators[e]=n},unregisterDecorator:function(e){delete this.decorators[e]},resetLoggedPropertyAccesses:function(){ha.resetLoggedProperties()}};var va=rt.default.log;j.log=va;j.createFrame=oe.createFrame;j.logger=rt.default});var oi=L((it,si)=>{"use strict";it.__esModule=!0;function ln(t){this.string=t}ln.prototype.toString=ln.prototype.toHTML=function(){return""+this.string};it.default=ln;si.exports=it.default});var ai=L(un=>{"use strict";un.__esModule=!0;un.wrapHelper=ya;function ya(t,e){if(typeof t!="function")return t;var n=function(){var i=arguments[arguments.length-1];return arguments[arguments.length-1]=e(i),t.apply(this,arguments)};return n}});var hi=L(Z=>{"use strict";Z.__esModule=!0;Z.checkRevision=Sa;Z.template=La;Z.wrapProgram=st;Z.resolvePartial=Ta;Z.invokePartial=_a;Z.noop=ci;function wa(t){return t&&t.__esModule?t:{default:t}}function ba(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e.default=t,e}var Ea=F(),z=ba(Ea),xa=X(),G=wa(xa),K=an(),li=Xt(),ka=ai(),ui=nn();function Sa(t){var e=t&&t[0]||1,n=K.COMPILER_REVISION;if(!(e>=K.LAST_COMPATIBLE_COMPILER_REVISION&&e<=K.COMPILER_REVISION))if(e{"use strict";ot.__esModule=!0;ot.default=function(t){var e=typeof global<"u"?global:window,n=e.Handlebars;t.noConflict=function(){return e.Handlebars===t&&(e.Handlebars=n),t}};fi.exports=ot.default});var ae=L((at,yi)=>{"use strict";at.__esModule=!0;function dn(t){return t&&t.__esModule?t:{default:t}}function hn(t){if(t&&t.__esModule)return t;var e={};if(t!=null)for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e.default=t,e}var Aa=an(),mi=hn(Aa),Ca=oi(),Ra=dn(Ca),Ma=X(),Ha=dn(Ma),Na=F(),cn=hn(Na),Da=hi(),gi=hn(Da),Ba=pi(),Qa=dn(Ba);function vi(){var t=new mi.HandlebarsEnvironment;return cn.extend(t,mi),t.SafeString=Ra.default,t.Exception=Ha.default,t.Utils=cn,t.escapeExpression=cn.escapeExpression,t.VM=gi,t.template=function(e){return gi.template(e,t)},t}var xe=vi();xe.create=vi;Qa.default(xe);xe.default=xe;at.default=xe;yi.exports=at.default});var zi=L((ji,Wi)=>{(function(){var t=function(e){var n=new t.Builder;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),n.searchPipeline.add(t.stemmer),e.call(n,n),n.build()};t.version="2.3.9";t.utils={},t.utils.warn=function(e){return function(n){e.console&&console.warn&&console.warn(n)}}(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var n=Object.create(null),r=Object.keys(e),i=0;i0){var c=t.utils.clone(n)||{};c.position=[a,u],c.index=s.length,s.push(new t.Token(r.slice(a,o),c))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,n){n in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index. -`,e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(r){var i=t.Pipeline.registeredFunctions[r];if(i)n.add(i);else throw new Error("Cannot load unregistered function: "+r)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(n){t.Pipeline.warnIfFunctionNotRegistered(n),this._stack.push(n)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");r=r+1,this._stack.splice(r,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");this._stack.splice(r,0,n)},t.Pipeline.prototype.remove=function(e){var n=this._stack.indexOf(e);n!=-1&&this._stack.splice(n,1)},t.Pipeline.prototype.run=function(e){for(var n=this._stack.length,r=0;r1&&(oe&&(r=s),o!=e);)i=r-n,s=n+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(ol?c+=2:a==l&&(n+=r[u+1]*i[c+1],u+=2,c+=2);return n},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),n=1,r=0;n0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new t.TokenSet;s.node.edges["*"]=l}if(s.str.length==0&&(l.final=!0),i.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new t.TokenSet;s.node.edges["*"]=u}s.str.length==1&&(u.final=!0),i.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var c=s.str.charAt(0),d=s.str.charAt(1),h;d in s.node.edges?h=s.node.edges[d]:(h=new t.TokenSet,s.node.edges[d]=h),s.str.length==1&&(h.final=!0),i.push({node:h,editsRemaining:s.editsRemaining-1,str:c+s.str.slice(2)})}}}return r},t.TokenSet.fromString=function(e){for(var n=new t.TokenSet,r=n,i=0,s=e.length;i=e;n--){var r=this.uncheckedNodes[n],i=r.child.toString();i in this.minimizedNodes?r.parent.edges[r.char]=this.minimizedNodes[i]:(r.child._str=i,this.minimizedNodes[i]=r.child),this.uncheckedNodes.pop()}};t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(n){var r=new t.QueryParser(e,n);r.parse()})},t.Index.prototype.query=function(e){for(var n=new t.Query(this.fields),r=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),l=0;l1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,n){var r=e[this._ref],i=Object.keys(this._fields);this._documents[r]=n||{},this.documentCount+=1;for(var s=0;s=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,n;do e=this.next(),n=e.charCodeAt(0);while(n>47&&n<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var n=e.next();if(n==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(n.charCodeAt(0)==92){e.escapeCharacter();continue}if(n==":")return t.QueryLexer.lexField;if(n=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(n=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(n=="+"&&e.width()===1||n=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(n.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,n){this.lexer=new t.QueryLexer(e),this.query=n,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var n=e.peekLexeme();if(n!=null)switch(n.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expected either a field or a term, found "+n.type;throw n.str.length>=1&&(r+=" with value '"+n.str+"'"),new t.QueryParseError(r,n.start,n.end)}},t.QueryParser.parsePresence=function(e){var n=e.consumeLexeme();if(n!=null){switch(n.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var r="unrecognised presence operator'"+n.str+"'";throw new t.QueryParseError(r,n.start,n.end)}var i=e.peekLexeme();if(i==null){var r="expecting term or field, found nothing";throw new t.QueryParseError(r,n.start,n.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(r,i.start,i.end)}}},t.QueryParser.parseField=function(e){var n=e.consumeLexeme();if(n!=null){if(e.query.allFields.indexOf(n.str)==-1){var r=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+n.str+"', possible fields: "+r;throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.fields=[n.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,n.start,n.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var n=e.consumeLexeme();if(n!=null){e.currentClause.term=n.str.toLowerCase(),n.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var r=e.peekLexeme();if(r==null){e.nextClause();return}switch(r.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+r.type+"'";throw new t.QueryParseError(i,r.start,r.end)}}},t.QueryParser.parseEditDistance=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="edit distance must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.editDistance=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="boost must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.boost=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},function(e,n){typeof define=="function"&&define.amd?define(n):typeof ji=="object"?Wi.exports=n():e.lunr=n()}(this,function(){return t})})()});var Yn=new URLSearchParams(window.location.search),Jn=window.self!==window.parent,Pt=Jn&&Yn.has("preview"),Ot=Jn&&Yn.has("hint"),A=Pt||Ot;function Ae(){return window.sidebarNodes||{}}function Xn(){return window.versionNodes||[]}var f=document.querySelector.bind(document),M=document.querySelectorAll.bind(document);function Zn(t){return t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function Re(t){return String(t).replace(/&/g,"&").replace(//g,">").replace(/"/g,""")}function Me(){return document.getElementById("main").dataset.type}var Ce=["H1","H2","H3","H4","H5","H6"];function He(t=!1){let e=window.location.hash.replace(/^#/,"");if(!e)return t?document.getElementById("top-content"):null;let n=document.getElementById(e);if(!n)return null;if(n.matches(".detail"))return n;if(Ce.includes(n.tagName))return It(n);let r=Ms(n);return r||document.getElementById("top-content")}function Ms(t){let e=t.previousElementSibling;for(;e;){if(Ce.includes(e.tagName))return It(e);e=e.previousElementSibling}let n=t.parentNode;for(;n;){for(e=n.previousElementSibling;e;){if(Ce.includes(e.tagName))return It(e);e=e.previousElementSibling}n=n.parentNode}return null}function It(t){let e=document.createElement("div"),n=[t],r=t;for(;(r=r.nextSibling)&&!(Ce.includes(r.tagName)&&r.tagName<=t.tagName);)n.push(r);return e.append(...n),e}function er(t){return new URLSearchParams(window.location.search).get(t)}function At(t){return fetch(t).then(e=>e.ok).catch(()=>!1)}function he(t){return!t||t.trim()===""}function tr(t,e){let n;return function(...i){clearTimeout(n),n=setTimeout(()=>{n=null,t(...i)},e)}}function Ne(){return document.head.querySelector("meta[name=project][content]").content}function De(){return document.documentElement.classList.contains("apple-os")}function E(t,e,n){let r=document.createElement(t);for(let i in e)e[i]!=null&&r.setAttribute(i,e[i]);return n&&r.replaceChildren(...n),r}if(Pt&&A){let t=He(!0);if(t){document.body.classList.add("preview"),document.getElementById("content").replaceChildren(...t.childNodes);let e=document.getElementsByTagName("a:not([target=_blank]");for(let n of e)n.setAttribute("target","_parent");window.scrollTo(0,0),document.body.style.position="fixed",setTimeout(nr),window.addEventListener("resize",nr)}}function nr(){let t={type:"preview",contentHeight:document.getElementById("content").parentElement.offsetHeight};window.parent.postMessage(t,"*")}var ie={plain:"plain",function:"function",module:"module"},Hs=[{href:"typespecs.html#basic-types",hint:{kind:ie.plain,description:"Basic type"}},{href:"typespecs.html#literals",hint:{kind:ie.plain,description:"Literal"}},{href:"typespecs.html#built-in-types",hint:{kind:ie.plain,description:"Built-in type"}}],Be={cancelHintFetching:null};function rr(t){if(sr(t))return!0;let e=/#.*\//;return t.includes("#")&&!e.test(t)?!1:t.includes(".html")}function ir(t){let e=sr(t);return e?Promise.resolve(e):Ns(t)}function sr(t){let e=Hs.find(n=>t.includes(n.href));return e?e.hint:null}function Ns(t){let e=t.replace(".html",".html?hint=true");return new Promise((n,r)=>{let i=document.createElement("iframe");i.setAttribute("src",e),i.style.display="none";function s(a){let{href:l,hint:u}=a.data;e===l&&(o(),n(u))}Be.cancelHintFetching=()=>{o(),r(new Error("cancelled"))};function o(){i.remove(),window.removeEventListener("message",s),Be.cancelHintFetching=null}window.addEventListener("message",s),document.body.appendChild(i)})}function or(){Be.cancelHintFetching&&Be.cancelHintFetching()}function ar(t){let n=t.querySelector("h1").textContent,r=t.querySelector(".docstring > p"),i=r?r.innerHTML:"";return{kind:ie.function,title:n.trim(),description:i.trim()}}function lr(t){let n=t.querySelector("h1 > span").textContent,r=t.querySelector("#moduledoc p"),i=r?r.innerHTML:"";return{kind:ie.module,title:n.trim(),description:i.trim()}}if(Ot&&A){let t=He(),e=t?ar(t):["modules","tasks"].includes(Me())?lr(f(".content-inner")):null;if(e){let n={hint:{...e,version:Ne()},href:window.location.href};window.parent.postMessage(n,"*")}f(".content-inner")?.replaceChildren()}var Ct="ex_doc:settings",ur="dark",Rt="system",Mt="dark",Ht="light";var Ds={tooltips:!0,theme:null,livebookUrl:null},Nt=class{constructor(){this._subscribers=[],this._settings=Ds,this._loadSettings()}get(){return this._settings}update(e){let n=this._settings;this._settings={...this._settings,...e},this._subscribers.forEach(r=>r(this._settings,n)),this._storeSettings()}getAndSubscribe(e){this._subscribers.push(e),e(this._settings)}_loadSettings(){try{let e=localStorage.getItem(Ct);if(e){let n=JSON.parse(e);this._settings={...this._settings,...n}}this._loadSettingsLegacy()}catch(e){console.error(`Failed to load settings: ${e}`)}}_storeSettings(){try{this._storeSettingsLegacy(),localStorage.setItem(Ct,JSON.stringify(this._settings))}catch(e){console.error(`Failed to persist settings: ${e}`)}}_loadSettingsLegacy(){localStorage.getItem("tooltipsDisabled")!==null&&(this._settings={...this._settings,tooltips:!1}),localStorage.getItem("night-mode")==="true"&&(this._settings={...this._settings,nightMode:!0}),this._settings.nightMode===!0&&(this._settings={...this._settings,theme:"dark"})}_storeSettingsLegacy(){this._settings.tooltips?localStorage.removeItem("tooltipsDisabled"):localStorage.setItem("tooltipsDisabled","true"),this._settings.nightMode!==null?localStorage.setItem("night-mode",this._settings.nightMode===!0?"true":"false"):localStorage.removeItem("night-mode"),this._settings.theme!==null?(localStorage.setItem("night-mode",this._settings.theme==="dark"?"true":"false"),this._settings.nightMode=this._settings.theme==="dark"):(delete this._settings.nightMode,localStorage.removeItem("night-mode"))}},H=new Nt;var cr=!1,Qe=null,J=null;function dr(t){cr||(cr=!0,J=document.getElementById("toast"),J?.addEventListener("click",()=>{clearTimeout(Qe),J.classList.remove("show")})),J&&(clearTimeout(Qe),J.innerText=t,J.classList.add("show"),Qe=setTimeout(()=>{J.classList.remove("show"),Qe=setTimeout(function(){J.innerText=""},1e3)},5e3))}var Dt=[Rt,Mt,Ht],hr=window.matchMedia("(prefers-color-scheme: dark)");H.getAndSubscribe(fr);hr.addEventListener("change",fr);function fr(){let t=qe(),e=t===Mt||t!==Ht&&hr.matches;document.body.classList.toggle(ur,e)}function pr(){let t=Dt[Dt.indexOf(qe())+1]||Dt[0];H.update({theme:t}),dr(`Set theme to "${t}"`)}function qe(){return new URLSearchParams(window.location.search).get("theme")||H.get().theme||Rt}var _r=Y(wr());var Qt="sidebar_state",qt="closed",br="open",Er="sidebar_width";var Ve="sidebar-open",$e="sidebar-transition";var xr=!1;function kr(){if(xr)return;xr=!0;let t=document.getElementById("sidebar-list-nav");if(!t)return;let e=Me(),n={extras:t.dataset.extras||"Pages",modules:"Modules",tasks:'Mix Tasks'};Object.entries(n).forEach(([r,i])=>{let s=Ae()[r];if(!s?.length)return;let o=`${r}-list-tab-button`,a=`${r}-tab-panel`,l=r===e,u=E("button",{id:o,role:"tab",tabindex:l?0:-1,"aria-selected":l||void 0,"aria-controls":a});u.innerHTML=i,u.addEventListener("keydown",ro),u.addEventListener("click",io),t.appendChild(E("li",{},[u]));let c=E("ul",{class:"full-list"});c.addEventListener("click",so);let d=E("div",{id:a,class:"sidebar-tabpanel",role:"tabpanel","aria-labelledby":o,hidden:l?void 0:""},[c]);document.getElementById("sidebar").appendChild(d);let h="",p,g;c.replaceChildren(...s.flatMap(m=>{let v=[],w=Array.isArray(m.headers),x=w?void 0:"no",P=m?.url||`${m.id}.html`;return m.group!==h&&(v.push(E("li",{class:"group",translate:x},[m.group])),h=m.group,p=void 0),m.nested_context&&m.nested_context!==p?(p=m.nested_context,g!==p&&v.push(E("li",{class:"nesting-context",translate:"no","aria-hidden":!0},[p]))):g=m.title,v.push(E("li",{},[E("a",{href:P,translate:x},[m.nested_title||m.title,m.url?E("i",{class:"external-link ri-external-link-line"}):null].filter(Boolean)),...Vt(`node-${m.id}-headers`,w?to(m):no(m))])),v}))}),Ft(),requestAnimationFrame(Sr),window.addEventListener("hashchange",Ft),window.addEventListener("exdoc:loaded",Ft)}function Vt(t,e){return e.length?[E("button",{"aria-label":"expand","aria-expanded":!1,"aria-controls":t}),E("ul",{id:t},e)]:[]}function to(t){return t.headers.map(({id:e,anchor:n})=>E("li",{},[E("a",{href:`${t.id}.html#${n}`},[e])]))}function no(t){let e=[];return t.sections?.length&&e.push(E("li",{},[E("a",{href:`${t.id}.html#content`},["Sections"]),...Vt(`${t.id}-sections-list`,t.sections.map(({id:n,anchor:r})=>E("li",{},[E("a",{href:`${t.id}.html#${r}`},[n])])))])),t.nodeGroups&&(e.push(E("li",{},[E("a",{href:`${t.id}.html#summary`},["Summary"])])),e.push(...t.nodeGroups.map(({key:n,name:r,nodes:i})=>E("li",{},[E("a",{href:`${t.id}.html#${n}`},[r]),...Vt(`node-${t.id}-group-${n}-list`,i.map(({anchor:s,title:o,id:a})=>E("li",{},[E("a",{href:`${t.id}.html#${s}`,title:o,translate:"no"},[a])])))])))),e}function $t(t){let e=document.getElementById("sidebar-list-nav").querySelector("[aria-selected]");e!==t&&(e&&(e.removeAttribute("aria-selected"),e.setAttribute("tabindex","-1"),document.getElementById(e.getAttribute("aria-controls")).setAttribute("hidden","hidden")),t.setAttribute("aria-selected","true"),t.setAttribute("tabindex","0"),document.getElementById(t.getAttribute("aria-controls")).removeAttribute("hidden"))}function Sr(){f("#sidebar [role=tabpanel]:not([hidden]) a[aria-selected]")?.scrollIntoView()}function Ft(){let t=document.getElementById("sidebar"),{pathname:e,hash:n}=window.location,r=e.split("/").pop().replace(/\.html$/,"")+".html",i=t.querySelector(`li a[href="${r+n}"]`)||t.querySelector(`li a[href="${r}"]`);if(!i)return;t.querySelectorAll(".full-list a[aria-selected]").forEach(o=>{o.removeAttribute("aria-selected")}),t.querySelectorAll(".full-list button[aria-expanded=true]").forEach(o=>{o.setAttribute("aria-expanded",!1)});let s=i.parentElement;for(;s;){if(s.tagName==="LI"){let o=s.firstChild;o.setAttribute("aria-selected",o.getAttribute("href")===r?"page":"true");let a=o.nextSibling;a?.tagName==="BUTTON"&&a.setAttribute("aria-expanded",!0)}else if(s.role==="tabpanel"){s.hasAttribute("hidden")&&$t(document.getElementById(s.getAttribute("aria-labelledby")));break}s=s.parentElement}}function ro(t){if(!["ArrowRight","ArrowLeft"].includes(t.key))return;let e=Array.from(M('#sidebar-list-nav [role="tab"]')),r=e.indexOf(t.currentTarget)+(t.key==="ArrowRight"?1:-1),i=e.at(r%e.length);$t(i),i.focus()}function io(t){$t(t.currentTarget),Sr()}function so(t){let e=t.target;e.tagName==="BUTTON"&&e.setAttribute("aria-expanded",e.getAttribute("aria-expanded")==="false")}var ao=300,Pr=".sidebar-toggle",Ut=window.matchMedia(`screen and (max-width: ${768}px)`);if(!A){window.addEventListener("exdoc:loaded",Lr);let t=document.getElementById("sidebar"),e=f(Pr);e.addEventListener("click",Ue),document.body.addEventListener("click",i=>{Ut.matches&&jt()&&!t.contains(i.target)&&!e.contains(i.target)&&Ue()});let n=window.innerWidth;window.addEventListener("resize",(0,_r.default)(()=>{n!==window.innerWidth&&(n=window.innerWidth,Lr())},100));let r=new ResizeObserver(([i])=>{if(!i)return;let s=i.contentRect.width;sessionStorage.setItem(Er,s),document.body.style.setProperty("--sidebarWidth",`${s}px`)});t.addEventListener("mousedown",()=>r.observe(t)),t.addEventListener("mouseup",()=>r.unobserve(t)),window.addEventListener("hashchange",lo)}function Lr(){let e=sessionStorage.getItem(Qt)!==qt&&!Ut.matches;Ir(e)}function Ue(){let t=!jt();return sessionStorage.setItem(Qt,t?br:qt),Wt(t)}function jt(){return document.body.classList.contains(Ve)}function Or(){return document.body.classList.contains(Ve)&&!document.body.classList.contains($e)}function Ir(t){t&&kr(),document.body.classList.toggle(Ve,t),f(Pr).setAttribute("aria-expanded",t?"true":"false")}var Tr;function Wt(t){return new Promise(e=>{document.body.classList.add($e),document.body.scrollTop,Ir(t),clearTimeout(Tr),Tr=setTimeout(()=>{document.body.classList.remove($e),e()},ao)})}function Ar(){return Wt(!0)}function lo(){Ut.matches&&jt()&&Wt(!1)}var wi=Y(ae());var fn=Y(ae());fn.registerHelper("isArray",function(t,e){return Array.isArray(t)?e.fn(this):e.inverse(this)});fn.registerHelper("isNonEmptyArray",function(t,e){return Array.isArray(t)&&t.length>0?e.fn(this):e.inverse(this)});var bi=wi.template({1:function(t,e,n,r,i){var s,o,a=e??(t.nullContext||{}),l=t.hooks.helperMissing,u="function",c=t.escapeExpression,d=t.lookupProperty||function(h,p){if(Object.prototype.hasOwnProperty.call(h,p))return h[p]};return' -`},2:function(t,e,n,r,i){return" selected disabled"},4:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return` -`},compiler:[8,">= 4.3.0"],main:function(t,e,n,r,i){var s,o=e??(t.nullContext||{}),a=t.lookupProperty||function(l,u){if(Object.prototype.hasOwnProperty.call(l,u))return l[u]};return`
- -`+((s=a(n,"if").call(o,e!=null?a(e,"latestVersion"):e,{name:"if",hash:{},fn:t.program(4,i,0),inverse:t.noop,data:i,loc:{start:{line:13,column:2},end:{line:19,column:9}}}))!=null?s:"")+`
-`},useData:!0});var qa=".sidebar-projectVersion",Ei=".sidebar-projectVersion select",Fa=".sidebar-staleVersion a";if(!A){let t=Xn(),e=f(qa);if(t.length>0||!e){let n=e.textContent.trim(),i=(t.some(u=>u.version===n)?t:[{version:n,url:"#"},...t]).map(u=>({...u,isCurrentVersion:u.version===n})),s=t.find(u=>u.latest),o=s?.version!==n&&!n.includes("-")?s?.url:null;e.innerHTML=bi({nodes:i,latestVersion:o});let a=f(Ei);a.addEventListener("change",$a),Va(a);let l=f(Fa);l&&l.addEventListener("click",Ua)}}function Va(t){let e=document.createElement("span");e.style.visibility="hidden",e.style.position="absolute",e.style.whiteSpace="nowrap",e.style.font=window.getComputedStyle(t).font,e.textContent=t.options[t.selectedIndex].text,document.body.appendChild(e),t.style.width=`${e.offsetWidth+20}px`,document.body.removeChild(e)}function $a(t){let e=t.target.value,n=window.location.pathname.split("/").pop()+window.location.hash,r=`${e}/${n}`;At(r).then(i=>{i?window.location.href=r:window.location.href=e})}function Ua(t){let e=this.href,n=window.location.pathname.split("/").pop()+window.location.hash,r=`${e}/${n}`;t.preventDefault(),At(r).then(i=>{i?window.location.href=r:window.location.href=e})}function pn(){let t=f(Ei);t&&(t.focus(),t.addEventListener("keydown",e=>{(e.key==="Escape"||e.key==="v")&&(e.preventDefault(),t.blur())}),navigator.userActivation.isActive&&"showPicker"in HTMLSelectElement.prototype&&t.showPicker())}var ja="content",Wa="tabs-open",za="tabs-close",Ga="H3",Ka="tabset";window.addEventListener("exdoc:loaded",Ya);function Ya(){let t=[],e=[],n=document.createNodeIterator(document.getElementById(ja),NodeFilter.SHOW_COMMENT,i=>i.nodeValue.trim()===Wa?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_REJECT),r;for(;r=n.nextNode();){let i=[];t.push([r,i]);let s,o=r;for(;o=o.nextSibling;)if(o.nodeName===Ga){s=[];let a=o.querySelector(".text")?.childNodes||o.childNodes;i.push([a,s]),e.push(o)}else if(o.nodeName==="#comment"&&o.nodeValue.trim()===za){e.push(o);break}else s&&s.push(o)}t.forEach(([i,s],o)=>{let a=E("div",{class:Ka});i.parentNode.replaceChild(a,i);let l=E("div",{role:"tablist",class:"tabset-tablist"});a.appendChild(l),s.forEach(([u,c],d)=>{let h=d===0,p=`tab-${o}-${d}`,g=`tabpanel-${o}-${d}`,m=E("button",{role:"tab",id:p,class:"tabset-tab",tabindex:h?0:-1,"aria-selected":h,"aria-controls":g},u);m.addEventListener("click",Ja),m.addEventListener("keydown",Xa),l.appendChild(m);let v=E("div",{role:"tabpanel",id:g,class:"tabset-panel",hidden:h?void 0:"",tabindex:h?0:-1,"aria-labelledby":p},c);a.appendChild(v)})}),e.forEach(i=>{i.parentNode.removeChild(i)})}function Ja(t){ki(t.currentTarget)}function Xa(t){if(xi[t.code]){t.preventDefault();let e=[...t.currentTarget.parentNode.childNodes],n=e.indexOf(t.currentTarget),r=xi[t.code](n,e.length);ki(e.at(r%e.length))}}var xi={ArrowLeft:t=>t-1,ArrowRight:t=>t+1,Home:()=>0,End:(t,e)=>e-1};function ki(t){let e=t.parentNode.querySelector("[aria-selected=true]");if(e===t)return;e.setAttribute("aria-selected","false"),e.tabIndex=-1,t.setAttribute("aria-selected","true"),t.tabIndex=0,t.focus();let n=document.getElementById(e.getAttribute("aria-controls"));n.setAttribute("hidden",""),n.tabIndex=-1;let r=document.getElementById(t.getAttribute("aria-controls"));r.removeAttribute("hidden"),r.tabIndex=0}window.addEventListener("exdoc:loaded",Za);function Za(){let t=window.location.pathname.replace(/(\.html)?$/,".livemd"),e=encodeURIComponent(new URL(t,window.location.href).toString());H.getAndSubscribe(({livebookUrl:n})=>{let r=n?`${n}/import?url=${e}`:`https://livebook.dev/run?url=${e}`;for(let i of M(".livebook-badge"))i.href=r})}var el="hll";window.addEventListener("exdoc:loaded",tl);function tl(){M("[data-group-id]").forEach(t=>{t.addEventListener("mouseenter",Si),t.addEventListener("mouseleave",Si)})}function Si(t){let e=t.currentTarget,n=t.type==="mouseenter",r=e.getAttribute("data-group-id");e.parentElement.querySelectorAll(`[data-group-id="${r}"]`).forEach(i=>{i.classList.toggle(el,n)})}var W={module:"module",moduleChild:"module-child",mixTask:"mix-task",extra:"extra",section:"section"};function Ti(t,e=8){if(he(t))return[];let n=Ae(),r=[...mn(n.modules,t,W.module,"module"),...nl(n.modules,t,W.moduleChild),...mn(n.tasks,t,W.mixTask,"mix task"),...mn(n.extras,t,W.extra,"page"),...gn(n.modules,t,W.section,"module"),...gn(n.tasks,t,W.section,"mix task"),...gn(n.extras,t,W.section,"page")].filter(i=>i!==null);return ul(r).slice(0,e)}function mn(t,e,n,r){return t.map(i=>i.searchData?null:il(i,e,n,r))}function nl(t,e,n){return t.filter(r=>r.nodeGroups).flatMap(r=>r.nodeGroups.flatMap(({key:i,nodes:s})=>{let o=ll(i);return s.map(a=>sl(a,r.id,e,n,o)||al(a,r.id,e,n,o))}))}function gn(t,e,n,r){return t.flatMap(i=>rl(i).map(s=>ol(i,s,e,n,r)))}function rl(t){return t.searchData?t.searchData:(t.sections||[]).concat(t.headers||[])}function il(t,e,n,r){return ut(t.title,e)?{link:`${t.id}.html`,title:ht(t.title,e),description:null,matchQuality:ct(t.title,e),deprecated:t.deprecated,labels:[r],category:n}:null}function sl(t,e,n,r,i){return ut(t.id,n)?{link:`${e}.html#${t.anchor}`,title:ht(t.id,n),labels:[i],description:e,matchQuality:ct(t.id,n),deprecated:t.deprecated,category:r}:null}function ol(t,e,n,r,i){if(!_i(e.id,n))return null;let s;return e.anchor===""?s=`${t.id}.html`:s=`${t.id}.html#${e.anchor}`,{link:s,title:ht(e.id,n),description:t.title,matchQuality:ct(e.id,n),labels:e.labels||[i,"section"],category:r}}function al(t,e,n,r,i){let s=`${e}.${t.id}`,o=`${e}:${t.id}`,a,l;if(ut(s,n))a=s,l=/\./g;else if(ut(o,n))a=o,l=/:/g;else return null;let u=n.replace(l," ");return _i(t.id,u)?{link:`${e}.html#${t.anchor}`,title:ht(t.id,u),label:i,description:e,matchQuality:ct(a,n),deprecated:t.deprecated,category:r}:null}function ll(t){switch(t){case"callbacks":return"callback";case"types":return"type";default:return"function"}}function ul(t){return t.slice().sort((e,n)=>e.matchQuality!==n.matchQuality?n.matchQuality-e.matchQuality:Li(e.category)-Li(n.category))}function Li(t){switch(t){case W.module:return 1;case W.moduleChild:return 2;case W.mixTask:return 3;default:return 4}}function _i(t,e){return dt(e).some(r=>Pi(t,r))}function ut(t,e){return dt(e).every(r=>Pi(t,r))}function Pi(t,e){return t.toLowerCase().includes(e.toLowerCase())}function ct(t,e){let n=dt(e),i=n.map(o=>o.length).reduce((o,a)=>o+a,0)/t.length,s=cl(t,n[0])?1:0;return i+s}function cl(t,e){return t.toLowerCase().startsWith(e.toLowerCase())}function dt(t){return t.trim().split(/\s+/)}function ht(t,e){let n=dt(e).sort((r,i)=>i.length-r.length);return lt(t,n)}function lt(t,e){if(e.length===0)return t;let[n,...r]=e,i=t.match(new RegExp(`(.*)(${Zn(n)})(.*)`,"i"));if(i){let[,s,o,a]=i;return lt(s,e)+""+Re(o)+""+lt(a,e)}else return lt(t,r)}var Oi=Y(ae());var Ii=Oi.template({1:function(t,e,n,r,i){var s,o,a=e??(t.nullContext||{}),l=t.hooks.helperMissing,u="function",c=t.escapeExpression,d=t.lookupProperty||function(h,p){if(Object.prototype.hasOwnProperty.call(h,p))return h[p]};return' -
-`+((s=d(n,"if").call(a,e!=null?d(e,"deprecated"):e,{name:"if",hash:{},fn:t.program(2,i,0),inverse:t.program(4,i,0),data:i,loc:{start:{line:16,column:10},end:{line:20,column:17}}}))!=null?s:"")+` -`+((s=d(n,"each").call(a,e!=null?d(e,"labels"):e,{name:"each",hash:{},fn:t.program(6,i,0),inverse:t.noop,data:i,loc:{start:{line:22,column:10},end:{line:24,column:19}}}))!=null?s:"")+`
- -
-
- -
-
- -`+((s=d(n,"if").call(a,e!=null?d(e,"description"):e,{name:"if",hash:{},fn:t.program(8,i,0),inverse:t.noop,data:i,loc:{start:{line:39,column:8},end:{line:43,column:15}}}))!=null?s:"")+`
-`},2:function(t,e,n,r,i){var s,o,a=t.lookupProperty||function(l,u){if(Object.prototype.hasOwnProperty.call(l,u))return l[u]};return' '+((s=(o=(o=a(n,"title")||(e!=null?a(e,"title"):e))!=null?o:t.hooks.helperMissing,typeof o=="function"?o.call(e??(t.nullContext||{}),{name:"title",hash:{},data:i,loc:{start:{line:17,column:49},end:{line:17,column:60}}}):o))!=null?s:"")+` -`},4:function(t,e,n,r,i){var s,o,a=t.lookupProperty||function(l,u){if(Object.prototype.hasOwnProperty.call(l,u))return l[u]};return' '+((s=(o=(o=a(n,"title")||(e!=null?a(e,"title"):e))!=null?o:t.hooks.helperMissing,typeof o=="function"?o.call(e??(t.nullContext||{}),{name:"title",hash:{},data:i,loc:{start:{line:19,column:46},end:{line:19,column:57}}}):o))!=null?s:"")+` -`},6:function(t,e,n,r,i){return' '+t.escapeExpression(t.lambda(e,e))+` -`},8:function(t,e,n,r,i){var s,o,a=t.lookupProperty||function(l,u){if(Object.prototype.hasOwnProperty.call(l,u))return l[u]};return`
- `+((s=(o=(o=a(n,"description")||(e!=null?a(e,"description"):e))!=null?o:t.hooks.helperMissing,typeof o=="function"?o.call(e??(t.nullContext||{}),{name:"description",hash:{},data:i,loc:{start:{line:41,column:10},end:{line:41,column:27}}}):o))!=null?s:"")+` -
-`},compiler:[8,">= 4.3.0"],main:function(t,e,n,r,i){var s,o,a=e??(t.nullContext||{}),l=t.lookupProperty||function(u,c){if(Object.prototype.hasOwnProperty.call(u,c))return u[c]};return`
-
-
-
- - Autocompletion results for "`+t.escapeExpression((o=(o=l(n,"term")||(e!=null?l(e,"term"):e))!=null?o:t.hooks.helperMissing,typeof o=="function"?o.call(a,{name:"term",hash:{},data:i,loc:{start:{line:6,column:55},end:{line:6,column:63}}}):o))+`" - - - Press RETURN for full-text search, TAB for previews - -
-
-`+((s=l(n,"each").call(a,e!=null?l(e,"suggestions"):e,{name:"each",hash:{},fn:t.program(1,i,0),inverse:t.noop,data:i,loc:{start:{line:13,column:6},end:{line:45,column:15}}}))!=null?s:"")+`
-
-
-`},useData:!0});var pe=".autocomplete",pt=".autocomplete-suggestions",ft=".autocomplete-suggestion",C={autocompleteSuggestions:[],previewOpen:!1,selectedIdx:-1};function dl(){f(pe).classList.add("shown")}function vn(){f(pe).classList.remove("shown")}function Ai(){return f(pe).classList.contains("shown")}function yn(t){C.autocompleteSuggestions=Ti(t),C.selectedIdx=-1,he(t)?vn():(hl({term:t,suggestions:C.autocompleteSuggestions}),mt(0),dl())}function hl({term:t,suggestions:e}){let n=Ii({suggestions:e,term:t}),r=f(pe);r.innerHTML=n}function wn(){return C.selectedIdx===-1?null:C.autocompleteSuggestions[C.selectedIdx]}function mt(t){Ri(fl(t))}function Ci(t){if(t.data.type==="preview"){let{contentHeight:e}=t.data,n=f(".autocomplete-preview");n&&(n.style.height=`${e+32}px`,n.classList.remove("loading"))}}function Ri(t){C.selectedIdx=t;let e=f(pt),n=f(`${ft}.selected`),r=f(`${ft}[data-index="${C.selectedIdx}"]`);if(n&&n.classList.remove("selected"),r){if(C.previewOpen){Hi(),window.addEventListener("message",Ci),e.classList.add("previewing");let i=document.createElement("div");i.classList.add("autocomplete-preview"),i.classList.add("loading");let s=r.href.replace(".html",`.html?preview=true&theme=${qe()}`),o=document.createElement("iframe");o.setAttribute("src",s),i.appendChild(document.createElement("div")),i.appendChild(document.createElement("span")),i.appendChild(o),r.parentNode.insertBefore(i,r.nextSibling)}r.classList.add("selected"),r.scrollIntoView({block:"nearest"})}else e&&(e.scrollTop=0)}function Mi(){C.previewOpen?gt():bn()}function gt(){C.previewOpen=!1;let t=f(pt);t&&t.classList.remove("previewing"),Hi()}function bn(t){C.previewOpen=!0,t?t=t.closest(ft):t=f(`${ft}[data-index="${C.selectedIdx}"]`),t&&Ri(parseInt(t.dataset.index))}function Hi(){let t=f(".autocomplete-preview");t&&(t.remove(),window.removeEventListener("message",Ci))}function fl(t){let e=C.autocompleteSuggestions.length+1;return(C.selectedIdx+t+1+e)%e-1}var ke="form.search-bar input",pl="form.search-bar .search-close-button";A||window.addEventListener("exdoc:loaded",ml);function ml(){gl(),window.onTogglePreviewClick=function(t,e){t.preventDefault(),t.stopImmediatePropagation(),xn(),e?bn(t.target):gt()}}function Bi(t){let e=f(ke);e.value=t}function xn(){let t=f(ke);document.body.classList.add("search-focused"),t.focus()}function gl(){let t=f(ke);if(document.querySelector('meta[name="exdoc:autocomplete"][content="off"]'))return t.addEventListener("keydown",e=>{e.key==="Enter"&&Ni(e)}),!0;t.addEventListener("keydown",e=>{let n=De();e.key==="Escape"?(vt(),t.blur()):e.key==="Enter"?Ni(e):e.key==="ArrowUp"||n&&e.ctrlKey&&e.key==="p"?(mt(-1),e.preventDefault()):e.key==="ArrowDown"||n&&e.ctrlKey&&e.key==="n"?(mt(1),e.preventDefault()):e.key==="Tab"&&wn()!==null&&(Mi(),e.preventDefault())}),t.addEventListener("input",e=>{yn(e.target.value)}),t.addEventListener("focus",e=>{document.body.classList.contains("search-focused")||(document.body.classList.add("search-focused"),yn(e.target.value))}),t.addEventListener("blur",e=>{let n=e.relatedTarget,r=f(pt);if(n&&r&&r.contains(n))return setTimeout(()=>{Ai()&&t.focus()},1e3),null;yt()}),f(pe).addEventListener("click",e=>{e.shiftKey||e.ctrlKey?t.focus():(vt(),yt())}),f(pl).addEventListener("click",e=>{vt(),yt()})}function Ni(t){let e=f(ke),n=t.shiftKey||t.ctrlKey,r=wn();t.preventDefault();let i=n?"_blank":"_self",s=document.createElement("a");if(s.setAttribute("target",i),r)s.setAttribute("href",r.link);else{let o=document.querySelector('meta[name="exdoc:full-text-search-url"]'),a=o?o.getAttribute("content"):"search.html?q=";s.setAttribute("href",`${a}${encodeURIComponent(e.value)}`)}s.click(),n||(vt(),yt())}function vt(){let t=f(ke);t.value=""}function yt(){gt(),document.body.classList.remove("search-focused"),vn()}var En,Di=2;window.addEventListener("scroll",function(){let t=window.scrollY;if(En!==void 0){let e=t-En;t===0||e>Di?document.body.classList.remove("scroll-sticky"):t>0&&-e>Di&&document.body.classList.add("scroll-sticky")}En=Math.max(0,t)},!1);var Qi=Y(ae());var qi=Qi.template({1:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return`
- `+t.escapeExpression(t.lambda((s=e!=null?o(e,"hint"):e)!=null?o(s,"description"):s,e))+` -
-`},3:function(t,e,n,r,i){var s,o=t.lambda,a=t.escapeExpression,l=t.lookupProperty||function(u,c){if(Object.prototype.hasOwnProperty.call(u,c))return u[c]};return`
-

- `+a(o((s=e!=null?l(e,"hint"):e)!=null?l(s,"title"):s,e))+` -
`+a(o((s=e!=null?l(e,"hint"):e)!=null?l(s,"version"):s,e))+`
-

-
-`+((s=l(n,"if").call(e??(t.nullContext||{}),(s=e!=null?l(e,"hint"):e)!=null?l(s,"description"):s,{name:"if",hash:{},fn:t.program(4,i,0),inverse:t.noop,data:i,loc:{start:{line:12,column:2},end:{line:16,column:9}}}))!=null?s:"")},4:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return`
- `+((s=t.lambda((s=e!=null?o(e,"hint"):e)!=null?o(s,"description"):s,e))!=null?s:"")+` -
-`},compiler:[8,">= 4.3.0"],main:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return(s=o(n,"if").call(e??(t.nullContext||{}),e!=null?o(e,"isPlain"):e,{name:"if",hash:{},fn:t.program(1,i,0),inverse:t.program(3,i,0),data:i,loc:{start:{line:1,column:0},end:{line:17,column:7}}}))!=null?s:""},useData:!0});var vl='
',yl='.content a:not([data-no-tooltip=""])',kn=".tooltip",Fi=".tooltip .tooltip-body",Vi="body .content-inner",wl="#content",$i="tooltip-shown",Se=10,bl=Se*4,El=768,xl=450,kl=100,le={currentLinkElement:null,hoverDelayTimeout:null};window.addEventListener("exdoc:loaded",Sl);function Sl(){M(yl).forEach(t=>{Ll(t)&&(t.addEventListener("mouseenter",_l),t.addEventListener("mouseleave",Ol))})}function Ll(t){return!(Tl(t.href)||!rr(t.href))}function Tl(t){let e=t.replace(wl,"");return window.location.href.split("#")[0]===e}function _l(t){if(window.innerWidth{ir(e.href).then(Pl).catch(()=>{})},kl)}function Pl(t){let e=qi({isPlain:t.kind===ie.plain,hint:t}),n=f(Fi);n||(f(Vi).insertAdjacentHTML("beforeend",vl),n=f(Fi)),n.innerHTML=e,Il(),f(kn).classList.add($i)}function Ol(){le.currentLinkElement&&(clearTimeout(le.hoverDelayTimeout),or(),le.currentLinkElement=null,f(kn)?.classList.remove($i))}function Il(){if(!le.currentLinkElement)return;let t=f(kn),e=le.currentLinkElement.getBoundingClientRect(),n=f(Vi).getBoundingClientRect(),r=t.getBoundingClientRect(),i=Al(e,n);if(e.left+r.width+Se code:first-child):not(:has(.copy-button))").forEach(t=>{if(!Sn){let r=document.createElement("div");r.innerHTML=Ui,Sn=r.firstChild}let e=Sn.cloneNode(!0);t.appendChild(e);let n;e.addEventListener("click",()=>{clearTimeout(n);let r=Array.from(t.querySelectorAll("code > *:not(.unselectable)")).map(i=>i.textContent).join("");navigator.clipboard.writeText(r),e.classList.add("clicked"),e.disabled=!0,n=setTimeout(()=>{e.classList.remove("clicked"),e.disabled=!1},3e3)})})}var V=Y(zi());var Gi=Y(ae());var Ki=Gi.template({1:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return" Search results for "+t.escapeExpression((s=(s=o(n,"value")||(e!=null?o(e,"value"):e))!=null?s:t.hooks.helperMissing,typeof s=="function"?s.call(e??(t.nullContext||{}),{name:"value",hash:{},data:i,loc:{start:{line:3,column:27},end:{line:3,column:36}}}):s))+` -`},3:function(t,e,n,r,i){return` Invalid search -`},5:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return(s=o(n,"each").call(e??(t.nullContext||{}),e!=null?o(e,"results"):e,{name:"each",hash:{},fn:t.program(6,i,0),inverse:t.noop,data:i,loc:{start:{line:10,column:2},end:{line:21,column:11}}}))!=null?s:""},6:function(t,e,n,r,i){var s,o=t.lambda,a=t.escapeExpression,l=t.lookupProperty||function(u,c){if(Object.prototype.hasOwnProperty.call(u,c))return u[c]};return`
-

- - `+a(o(e!=null?l(e,"title"):e,e))+" ("+a(o(e!=null?l(e,"type"):e,e))+`) - -

-`+((s=l(n,"each").call(e??(t.nullContext||{}),e!=null?l(e,"excerpts"):e,{name:"each",hash:{},fn:t.program(7,i,0),inverse:t.noop,data:i,loc:{start:{line:17,column:8},end:{line:19,column:17}}}))!=null?s:"")+`
-`},7:function(t,e,n,r,i){var s;return'

'+((s=t.lambda(e,e))!=null?s:"")+`

-`},9:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return((s=(o(n,"isArray")||e&&o(e,"isArray")||t.hooks.helperMissing).call(e??(t.nullContext||{}),e!=null?o(e,"results"):e,{name:"isArray",hash:{},fn:t.program(10,i,0),inverse:t.program(12,i,0),data:i,loc:{start:{line:23,column:2},end:{line:29,column:14}}}))!=null?s:"")+` -

The search functionality is full-text based. Here are some tips:

- -
    -
  • Multiple words (such as foo bar) are searched as OR
  • -
  • Use * anywhere (such as fo*) as wildcard
  • -
  • Use + before a word (such as +foo) to make its presence required
  • -
  • Use - before a word (such as -foo) to make its absence required
  • -
  • Use : to search on a particular field (such as field:word). The available fields are title, doc and type
  • -
  • Use WORD^NUMBER (such as foo^2) to boost the given word
  • -
  • Use WORD~NUMBER (such as foo~2) to do a search with edit distance on word
  • -
- -

To quickly go to a module, type, or function, use the autocompletion feature in the sidebar search.

-`},10:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return"

Sorry, we couldn't find anything for "+t.escapeExpression((s=(s=o(n,"value")||(e!=null?o(e,"value"):e))!=null?s:t.hooks.helperMissing,typeof s=="function"?s.call(e??(t.nullContext||{}),{name:"value",hash:{},data:i,loc:{start:{line:24,column:48},end:{line:24,column:57}}}):s))+`.

-`},12:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return(s=o(n,"if").call(e??(t.nullContext||{}),e!=null?o(e,"value"):e,{name:"if",hash:{},fn:t.program(13,i,0),inverse:t.program(15,i,0),data:i,loc:{start:{line:25,column:2},end:{line:29,column:2}}}))!=null?s:""},13:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return"

Invalid search: "+t.escapeExpression((s=(s=o(n,"errorMessage")||(e!=null?o(e,"errorMessage"):e))!=null?s:t.hooks.helperMissing,typeof s=="function"?s.call(e??(t.nullContext||{}),{name:"errorMessage",hash:{},data:i,loc:{start:{line:26,column:23},end:{line:26,column:39}}}):s))+`.

-`},15:function(t,e,n,r,i){return`

Please type something into the search bar to perform a search.

- `},compiler:[8,">= 4.3.0"],main:function(t,e,n,r,i){var s,o=e??(t.nullContext||{}),a=t.lookupProperty||function(l,u){if(Object.prototype.hasOwnProperty.call(l,u))return l[u]};return`

-`+((s=a(n,"if").call(o,e!=null?a(e,"value"):e,{name:"if",hash:{},fn:t.program(1,i,0),inverse:t.program(3,i,0),data:i,loc:{start:{line:2,column:2},end:{line:6,column:9}}}))!=null?s:"")+`

- -`+((s=(a(n,"isNonEmptyArray")||e&&a(e,"isNonEmptyArray")||t.hooks.helperMissing).call(o,e!=null?a(e,"results"):e,{name:"isNonEmptyArray",hash:{},fn:t.program(5,i,0),inverse:t.program(9,i,0),data:i,loc:{start:{line:9,column:0},end:{line:44,column:20}}}))!=null?s:"")},useData:!0});var wt=80,Rl="#search";V.default.tokenizer.separator=/\s+/;V.default.QueryLexer.termSeparator=/\s+/;V.default.Pipeline.registerFunction(Xi,"docTokenSplitter");V.default.Pipeline.registerFunction(Zi,"docTrimmer");window.addEventListener("exdoc:loaded",Ml);function Ml(){let t=window.location.pathname;if(t.endsWith("/search.html")||t.endsWith("/search")){let e=er("q");Hl(e)}}async function Hl(t){if(he(t))Ln({value:t});else{Bi(t);let e=await Nl();try{let n=t.replaceAll(/(\B|\\):/g,"\\:"),r=Wl(e.search(n));Ln({value:t,results:r})}catch(n){Ln({value:t,errorMessage:n.message})}}}function Ln({value:t,results:e,errorMessage:n}){let r=f(Rl),i=Ki({value:t,results:e,errorMessage:n});r.innerHTML=i}async function Nl(){let t=await Dl();if(t)return t;let e=$l();return Bl(e),e}async function Dl(){try{let t=sessionStorage.getItem(Ji());if(t){let e=await ql(t);return V.default.Index.load(e)}else return null}catch(t){return console.error("Failed to load index: ",t),null}}async function Bl(t){try{let e=await Ql(t);sessionStorage.setItem(Ji(),e)}catch(e){console.error("Failed to save index: ",e)}}async function Ql(t){let e=new Blob([JSON.stringify(t)],{type:"application/json"}).stream().pipeThrough(new window.CompressionStream("gzip")),r=await(await new Response(e).blob()).arrayBuffer();return Fl(r)}async function ql(t){let e=new Blob([Vl(t)],{type:"application/json"}).stream().pipeThrough(new window.DecompressionStream("gzip")),n=await new Response(e).text();return JSON.parse(n)}function Fl(t){let e="",n=new Uint8Array(t),r=n.byteLength;for(let i=0;i{this.add(t)})})}function Ul(t){t.pipeline.before(V.default.stemmer,Xi)}function Xi(t){let e=[t],n=/\/\d+$/,r=/\:|\./,i=t.toString();if(i.replace(/^[.,;?!]+|[.,;]+$/g,""),i.startsWith("`")&&i.endsWith("`")&&(i=i.slice(1,-1)),n.test(i)){let o=t.toString().replace(n,"");e.push(t.clone().update(()=>o));let a=o.split(r);if(a.length>1){for(let u of a)e.push(t.clone().update(()=>u));let l=t.toString().split(r);e.push(t.clone().update(()=>l[l.length-1]))}i=a[a.length-1]}else i.startsWith("@")?(i=i.substring(1),e.push(t.clone().update(()=>i))):i.startsWith(":")&&(i=i.substring(1),e.push(t.clone().update(()=>i)));let s=i.split(/\_|\-/);if(s.length>1)for(let o of s)e.push(t.clone().update(()=>o));return e}function jl(t){t.pipeline.before(V.default.stemmer,Zi)}function Zi(t){return t.update(function(e){return e.replace(/^[^@:\w]+/,"").replace(/[^\?\!\w]+$/,"")})}function Wl(t){return t.filter(e=>Yi(e.ref)).map(e=>{let n=Yi(e.ref),r=e.matchData.metadata;return{...n,metadata:r,excerpts:zl(n,r)}})}function Yi(t){return searchData.items.find(e=>e.ref===t)||null}function zl(t,e){let{doc:n}=t,i=Object.keys(e).filter(s=>"doc"in e[s]).map(s=>e[s].doc.position.map(([o,a])=>Gl(n,o,a))).reduce((s,o)=>s.concat(o),[]);return i.length===0?[n.slice(0,wt*2)+(wt*20?"...":"",t.slice(r,e),""+Re(t.slice(e,e+n))+"",t.slice(e+n,i),i{t.key==="Escape"&&ue()}),N.querySelector(".modal-close").addEventListener("click",ue),N.addEventListener("click",t=>{t.target===N&&ue()}))}function ts(t){if(!_n)if(N.contains(t.target))Tn=t.target;else{_n=!0;let e=N.querySelectorAll(Kl);Tn===e[0]?e[e.length-1].focus():e[0].focus(),_n=!1,Tn=document.activeElement}}function bt({title:t,body:e}){Yl(),Pn=document.activeElement,document.addEventListener("focus",ts,!0),N.querySelector(".modal-title").innerHTML=t,N.querySelector(".modal-body").innerHTML=e,N.classList.add("shown"),N.focus()}function ue(){N?.classList.remove("shown"),document.removeEventListener("focus",ts,!0),Pn?.focus(),Pn=null}function ns(){return Boolean(N?.classList.contains("shown"))}var rs='
';var Jl="https://hexdocs.pm/%%",Xl="https://www.erlang.org/doc/apps/%%",Zl="https://hex.pm/api/packages?search=name:%%*",eu=".display-quick-switch",ss="#quick-switch-input",os="#quick-switch-results",tu=300,nu=9,as=["erts","asn1","common_test","compiler","crypto","debugger","dialyzer","diameter","edoc","eldap","erl_interface","et","eunit","ftp","inets","jinterface","kernel","megaco","mnesia","observer","odbc","os_mon","parsetools","public_key","reltool","runtime_tools","sasl","snmp","ssh","ssl","stdlib","syntax_tools","tftp","tools","wx","xmerl"],ru=["elixir","eex","ex_unit","hex","iex","logger","mix"].concat(as).map(t=>({name:t})),ls=2,B={autocompleteResults:[],selectedIdx:null};A||window.addEventListener("exdoc:loaded",iu);function iu(){M(eu).forEach(t=>{t.addEventListener("click",In)})}function su(t){if(t.key==="Enter"){let e=t.target.value;au(e),t.preventDefault()}else t.key==="ArrowUp"?(is(-1),t.preventDefault()):t.key==="ArrowDown"&&(is(1),t.preventDefault())}function ou(t){let e=t.target.value;if(e.lengthn.json()).then(n=>{Array.isArray(n)&&(B.autocompleteResults=du(t,n),B.selectedIdx=null,f(ss).value.length>=ls&&cu(B.autocompleteResults))})}function cu(t){f(os).replaceChildren(...t.map(({name:e},n)=>{let r=E("div",{class:"quick-switch-result","data-index":n},[e]);return r.addEventListener("click",()=>On(e)),r}))}function du(t,e){return ru.concat(e).filter(n=>n.name.toLowerCase().includes(t.toLowerCase())).filter(n=>n.releases===void 0||n.releases[0].has_docs===!0).slice(0,nu)}function is(t){B.selectedIdx=hu(t);let e=f(".quick-switch-result.selected"),n=f(`.quick-switch-result[data-index="${B.selectedIdx}"]`);e&&e.classList.remove("selected"),n&&n.classList.add("selected")}function hu(t){let e=B.autocompleteResults.length;if(B.selectedIdx===null){if(t>=0)return 0;if(t<0)return e-1}return(B.selectedIdx+t+e)%e}var fu="#settings-modal-content",Rn=[{key:"c",description:"Toggle sidebar",action:Ue},{key:"n",description:"Cycle themes",action:pr},{key:"s",description:"Focus search bar",displayAs:"/ or s",action:An},{key:"/",action:An},{key:"k",hasModifier:!0,action:An},{key:"v",description:"Open/focus version select",action:gu},{key:"g",description:"Go to package docs",displayAs:"g",action:In},{key:"?",displayAs:"?",description:"Bring up this modal",action:vu}],Cn={shortcutBeingPressed:null};A||(document.addEventListener("keydown",pu),document.addEventListener("keyup",mu));function pu(t){if(Cn.shortcutBeingPressed||t.target.matches("input, select, textarea"))return;let e=Rn.find(n=>n.hasModifier?De()&&t.metaKey||t.ctrlKey?n.key===t.key:!1:t.ctrlKey||t.metaKey||t.altKey?!1:n.key===t.key);e&&(Cn.shortcutBeingPressed=e,t.preventDefault(),e.action(t))}function mu(t){Cn.shortcutBeingPressed=null}function An(t){ue(),xn()}function gu(){ue(),Or()?pn():Ar().then(pn)}function vu(){yu()?ue():Mn()}function yu(){return ns()&&f(fu)}var us=Y(ae());var cs=us.template({1:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return(s=o(n,"if").call(e??(t.nullContext||{}),e!=null?o(e,"description"):e,{name:"if",hash:{},fn:t.program(2,i,0),inverse:t.noop,data:i,loc:{start:{line:40,column:6},end:{line:53,column:13}}}))!=null?s:""},2:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return`
-
- `+t.escapeExpression(t.lambda(e!=null?o(e,"description"):e,e))+` -
-
-`+((s=o(n,"if").call(e??(t.nullContext||{}),e!=null?o(e,"displayAs"):e,{name:"if",hash:{},fn:t.program(3,i,0),inverse:t.program(5,i,0),data:i,loc:{start:{line:46,column:12},end:{line:50,column:19}}}))!=null?s:"")+`
-
-`},3:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return" "+((s=t.lambda(e!=null?o(e,"displayAs"):e,e))!=null?s:"")+` -`},5:function(t,e,n,r,i){var s=t.lookupProperty||function(o,a){if(Object.prototype.hasOwnProperty.call(o,a))return o[a]};return" "+t.escapeExpression(t.lambda(e!=null?s(e,"key"):e,e))+` -`},compiler:[8,">= 4.3.0"],main:function(t,e,n,r,i){var s,o=t.lookupProperty||function(a,l){if(Object.prototype.hasOwnProperty.call(a,l))return a[l]};return`
-
- - - - -
- -
-`},useData:!0});var wu=".display-settings",bu="#settings-modal-content",Hn="#modal-settings-tab",Nn="#modal-keyboard-shortcuts-tab",hs="#settings-content",fs="#keyboard-shortcuts-content",Eu=[{title:"Settings",id:"modal-settings-tab"},{title:"Keyboard shortcuts",id:"modal-keyboard-shortcuts-tab"}];window.addEventListener("exdoc:loaded",xu);function xu(){M(wu).forEach(t=>{t.addEventListener("click",Mn)})}function ds(){f(Nn).classList.remove("active"),f(Hn).classList.add("active"),f(hs).classList.remove("hidden"),f(fs).classList.add("hidden")}function ku(){f(Nn).classList.add("active"),f(Hn).classList.remove("active"),f(fs).classList.remove("hidden"),f(hs).classList.add("hidden")}function Mn(){bt({title:Eu.map(({id:s,title:o})=>``).join(""),body:cs({shortcuts:Rn})});let t=f(bu),e=t.querySelector('[name="theme"]'),n=t.querySelector('[name="tooltips"]'),r=t.querySelector('[name="direct_livebook_url"]'),i=t.querySelector('[name="livebook_url"]');H.getAndSubscribe(s=>{e.value=s.theme||"system",n.checked=s.tooltips,s.livebookUrl===null?(r.checked=!1,i.classList.add("hidden"),i.tabIndex=-1):(r.checked=!0,i.classList.remove("hidden"),i.tabIndex=0,i.value=s.livebookUrl)}),e.addEventListener("change",s=>{H.update({theme:s.target.value})}),n.addEventListener("change",s=>{H.update({tooltips:s.target.checked})}),r.addEventListener("change",s=>{let o=s.target.checked?i.value:null;H.update({livebookUrl:o})}),i.addEventListener("input",s=>{H.update({livebookUrl:s.target.value})}),f(Hn).addEventListener("click",s=>{ds()}),f(Nn).addEventListener("click",s=>{ku()}),ds()}var Dn=new WeakMap;function Bn(t,e,n,r){if(!t&&!Dn.has(e))return!1;let i=Dn.get(e)??new WeakMap;Dn.set(e,i);let s=i.get(n)??new Set;i.set(n,s);let o=s.has(r);return t?s.add(r):s.delete(r),o&&t}function Su(t,e){let n=t.target;if(n instanceof Text&&(n=n.parentElement),n instanceof Element&&t.currentTarget instanceof Element){let r=n.closest(e);if(r&&t.currentTarget.contains(r))return r}}function Lu(t,e,n,r={}){let{signal:i,base:s=document}=r;if(i?.aborted)return;let{once:o,...a}=r,l=s instanceof Document?s.documentElement:s,u=Boolean(typeof r=="object"?r.capture:r),c=p=>{let g=Su(p,String(t));if(g){let m=Object.assign(p,{delegateTarget:g});n.call(l,m),o&&(l.removeEventListener(e,c,a),Bn(!1,l,n,d))}},d=JSON.stringify({selector:t,type:e,capture:u});Bn(!0,l,n,d)||l.addEventListener(e,c,a),i?.addEventListener("abort",()=>{Bn(!1,l,n,d)})}var Et=Lu;function O(){return O=Object.assign?Object.assign.bind():function(t){for(var e=1;eString(t).toLowerCase().replace(/[\s/_.]+/g,"-").replace(/[^\w-]+/g,"").replace(/--+/g,"-").replace(/^-+|-+$/g,"")||e||"",Te=({hash:t}={})=>window.location.pathname+window.location.search+(t?window.location.hash:""),Tu=(t,e={})=>{let n=O({url:t=t||Te({hash:!0}),random:Math.random(),source:"swup"},e);window.history.pushState(n,"",t)},Le=(t=null,e={})=>{t=t||Te({hash:!0});let n=O({},window.history.state||{},{url:t,random:Math.random(),source:"swup"},e);window.history.replaceState(n,"",t)},_u=(t,e,n,r)=>{let i=new AbortController;return r=O({},r,{signal:i.signal}),Et(t,e,n,r),{destroy:()=>i.abort()}},I=class extends URL{constructor(e,n=document.baseURI){super(e.toString(),n),Object.setPrototypeOf(this,I.prototype)}get url(){return this.pathname+this.search}static fromElement(e){let n=e.getAttribute("href")||e.getAttribute("xlink:href")||"";return new I(n)}static fromUrl(e){return new I(e)}};var me=class extends Error{constructor(e,n){super(e),this.url=void 0,this.status=void 0,this.aborted=void 0,this.timedOut=void 0,this.name="FetchError",this.url=n.url,this.status=n.status,this.aborted=n.aborted||!1,this.timedOut=n.timedOut||!1}};async function Pu(t,e={}){var n;t=I.fromUrl(t).url;let{visit:r=this.visit}=e,i=O({},this.options.requestHeaders,e.headers),s=(n=e.timeout)!=null?n:this.options.timeout,o=new AbortController,{signal:a}=o;e=O({},e,{headers:i,signal:a});let l,u=!1,c=null;s&&s>0&&(c=setTimeout(()=>{u=!0,o.abort("timeout")},s));try{l=await this.hooks.call("fetch:request",r,{url:t,options:e},(v,{url:w,options:x})=>fetch(w,x)),c&&clearTimeout(c)}catch(v){throw u?(this.hooks.call("fetch:timeout",r,{url:t}),new me(`Request timed out: ${t}`,{url:t,timedOut:u})):v?.name==="AbortError"||a.aborted?new me(`Request aborted: ${t}`,{url:t,aborted:!0}):v}let{status:d,url:h}=l,p=await l.text();if(d===500)throw this.hooks.call("fetch:error",r,{status:d,response:l,url:h}),new me(`Server error: ${h}`,{status:d,url:h});if(!p)throw new me(`Empty response: ${h}`,{status:d,url:h});let{url:g}=I.fromUrl(h),m={url:g,html:p};return!r.cache.write||e.method&&e.method!=="GET"||t!==g||this.cache.set(m.url,m),m}var qn=class{constructor(e){this.swup=void 0,this.pages=new Map,this.swup=e}get size(){return this.pages.size}get all(){let e=new Map;return this.pages.forEach((n,r)=>{e.set(r,O({},n))}),e}has(e){return this.pages.has(this.resolve(e))}get(e){let n=this.pages.get(this.resolve(e));return n&&O({},n)}set(e,n){n=O({},n,{url:e=this.resolve(e)}),this.pages.set(e,n),this.swup.hooks.callSync("cache:set",void 0,{page:n})}update(e,n){e=this.resolve(e);let r=O({},this.get(e),n,{url:e});this.pages.set(e,r)}delete(e){this.pages.delete(this.resolve(e))}clear(){this.pages.clear(),this.swup.hooks.callSync("cache:clear",void 0,void 0)}prune(e){this.pages.forEach((n,r)=>{e(r,n)&&this.delete(r)})}resolve(e){let{url:n}=I.fromUrl(e);return this.swup.resolveUrl(n)}},Fn=(t,e=document)=>e.querySelector(t),Un=(t,e=document)=>Array.from(e.querySelectorAll(t)),ys=()=>new Promise(t=>{requestAnimationFrame(()=>{requestAnimationFrame(()=>{t()})})});function ws(t){return!!t&&(typeof t=="object"||typeof t=="function")&&typeof t.then=="function"}function Ou(t,e=[]){return new Promise((n,r)=>{let i=t(...e);ws(i)?i.then(n,r):n(i)})}function ps(t,e){let n=t?.closest(`[${e}]`);return n!=null&&n.hasAttribute(e)?n?.getAttribute(e)||!0:void 0}var Vn=class{constructor(e){this.swup=void 0,this.swupClasses=["to-","is-changing","is-rendering","is-popstate","is-animating","is-leaving"],this.swup=e}get selectors(){let{scope:e}=this.swup.visit.animation;return e==="containers"?this.swup.visit.containers:e==="html"?["html"]:Array.isArray(e)?e:[]}get selector(){return this.selectors.join(",")}get targets(){return this.selector.trim()?Un(this.selector):[]}add(...e){this.targets.forEach(n=>n.classList.add(...e))}remove(...e){this.targets.forEach(n=>n.classList.remove(...e))}clear(){this.targets.forEach(e=>{let n=e.className.split(" ").filter(r=>this.isSwupClass(r));e.classList.remove(...n)})}isSwupClass(e){return this.swupClasses.some(n=>e.startsWith(n))}},St=class{constructor(e,n){this.id=void 0,this.state=void 0,this.from=void 0,this.to=void 0,this.containers=void 0,this.animation=void 0,this.trigger=void 0,this.cache=void 0,this.history=void 0,this.scroll=void 0,this.meta=void 0;let{to:r,from:i,hash:s,el:o,event:a}=n;this.id=Math.random(),this.state=1,this.from={url:i??e.location.url,hash:e.location.hash},this.to={url:r,hash:s},this.containers=e.options.containers,this.animation={animate:!0,wait:!1,name:void 0,native:e.options.native,scope:e.options.animationScope,selector:e.options.animationSelector},this.trigger={el:o,event:a},this.cache={read:e.options.cache,write:e.options.cache},this.history={action:"push",popstate:!1,direction:void 0},this.scroll={reset:!0,target:void 0},this.meta={}}advance(e){this.state=7}};function Iu(t){return new St(this,t)}var $n=class{constructor(e){this.swup=void 0,this.registry=new Map,this.hooks=["animation:out:start","animation:out:await","animation:out:end","animation:in:start","animation:in:await","animation:in:end","animation:skip","cache:clear","cache:set","content:replace","content:scroll","enable","disable","fetch:request","fetch:error","fetch:timeout","history:popstate","link:click","link:self","link:anchor","link:newtab","page:load","page:view","scroll:top","scroll:anchor","visit:start","visit:transition","visit:abort","visit:end"],this.swup=e,this.init()}init(){this.hooks.forEach(e=>this.create(e))}create(e){this.registry.has(e)||this.registry.set(e,new Map)}exists(e){return this.registry.has(e)}get(e){let n=this.registry.get(e);if(n)return n;console.error(`Unknown hook '${e}'`)}clear(){this.registry.forEach(e=>e.clear())}on(e,n,r={}){let i=this.get(e);if(!i)return console.warn(`Hook '${e}' not found.`),()=>{};let s=O({},r,{id:i.size+1,hook:e,handler:n});return i.set(n,s),()=>this.off(e,n)}before(e,n,r={}){return this.on(e,n,O({},r,{before:!0}))}replace(e,n,r={}){return this.on(e,n,O({},r,{replace:!0}))}once(e,n,r={}){return this.on(e,n,O({},r,{once:!0}))}off(e,n){let r=this.get(e);r&&n?r.delete(n)||console.warn(`Handler for hook '${e}' not found.`):r&&r.clear()}async call(e,n,r,i){let[s,o,a]=this.parseCallArgs(e,n,r,i),{before:l,handler:u,after:c}=this.getHandlers(e,a);await this.run(l,s,o);let[d]=await this.run(u,s,o,!0);return await this.run(c,s,o),this.dispatchDomEvent(e,s,o),d}callSync(e,n,r,i){let[s,o,a]=this.parseCallArgs(e,n,r,i),{before:l,handler:u,after:c}=this.getHandlers(e,a);this.runSync(l,s,o);let[d]=this.runSync(u,s,o,!0);return this.runSync(c,s,o),this.dispatchDomEvent(e,s,o),d}parseCallArgs(e,n,r,i){return n instanceof St||typeof n!="object"&&typeof r!="function"?[n,r,i]:[void 0,n,r]}async run(e,n=this.swup.visit,r,i=!1){let s=[];for(let{hook:o,handler:a,defaultHandler:l,once:u}of e)if(n==null||!n.done){u&&this.off(o,a);try{let c=await Ou(a,[n,r,l]);s.push(c)}catch(c){if(i)throw c;console.error(`Error in hook '${o}':`,c)}}return s}runSync(e,n=this.swup.visit,r,i=!1){let s=[];for(let{hook:o,handler:a,defaultHandler:l,once:u}of e)if(n==null||!n.done){u&&this.off(o,a);try{let c=a(n,r,l);s.push(c),ws(c)&&console.warn(`Swup will not await Promises in handler for synchronous hook '${o}'.`)}catch(c){if(i)throw c;console.error(`Error in hook '${o}':`,c)}}return s}getHandlers(e,n){let r=this.get(e);if(!r)return{found:!1,before:[],handler:[],after:[],replaced:!1};let i=Array.from(r.values()),s=this.sortRegistrations,o=i.filter(({before:d,replace:h})=>d&&!h).sort(s),a=i.filter(({replace:d})=>d).filter(d=>!0).sort(s),l=i.filter(({before:d,replace:h})=>!d&&!h).sort(s),u=a.length>0,c=[];if(n&&(c=[{id:0,hook:e,handler:n}],u)){let d=a.length-1,{handler:h,once:p}=a[d],g=m=>{let v=a[m-1];return v?(w,x)=>v.handler(w,x,g(m-1)):n};c=[{id:0,hook:e,once:p,handler:h,defaultHandler:g(d)}]}return{found:!0,before:o,handler:c,after:l,replaced:u}}sortRegistrations(e,n){var r,i;return((r=e.priority)!=null?r:0)-((i=n.priority)!=null?i:0)||e.id-n.id||0}dispatchDomEvent(e,n,r){if(n!=null&&n.done)return;let i={hook:e,args:r,visit:n||this.swup.visit};document.dispatchEvent(new CustomEvent("swup:any",{detail:i,bubbles:!0})),document.dispatchEvent(new CustomEvent(`swup:${e}`,{detail:i,bubbles:!0}))}parseName(e){let[n,...r]=e.split(".");return[n,r.reduce((i,s)=>O({},i,{[s]:!0}),{})]}},Au=t=>{if(t&&t.charAt(0)==="#"&&(t=t.substring(1)),!t)return null;let e=decodeURIComponent(t),n=document.getElementById(t)||document.getElementById(e)||Fn(`a[name='${CSS.escape(t)}']`)||Fn(`a[name='${CSS.escape(e)}']`);return n||t!=="top"||(n=document.body),n},xt="transition",Qn="animation";async function Cu({selector:t,elements:e}){if(t===!1&&!e)return;let n=[];if(e)n=Array.from(e);else if(t&&(n=Un(t,document.body),!n.length))return void console.warn(`[swup] No elements found matching animationSelector \`${t}\``);let r=n.map(i=>function(s){let{type:o,timeout:a,propCount:l}=function(u){let c=window.getComputedStyle(u),d=kt(c,`${xt}Delay`),h=kt(c,`${xt}Duration`),p=ms(d,h),g=kt(c,`${Qn}Delay`),m=kt(c,`${Qn}Duration`),v=ms(g,m),w=Math.max(p,v),x=w>0?p>v?xt:Qn:null;return{type:x,timeout:w,propCount:x?x===xt?h.length:m.length:0}}(s);return!(!o||!a)&&new Promise(u=>{let c=`${o}end`,d=performance.now(),h=0,p=()=>{s.removeEventListener(c,g),u()},g=m=>{m.target===s&&((performance.now()-d)/1e3=l&&p())};setTimeout(()=>{h0?await Promise.all(r):t&&console.warn(`[swup] No CSS animation duration defined on elements matching \`${t}\``)}function kt(t,e){return(t[e]||"").split(", ")}function ms(t,e){for(;t.lengthgs(n)+gs(t[r])))}function gs(t){return 1e3*parseFloat(t)}function Ru(t,e={},n={}){if(typeof t!="string")throw new Error("swup.navigate() requires a URL parameter");if(this.shouldIgnoreVisit(t,{el:n.el,event:n.event}))return void window.location.assign(t);let{url:r,hash:i}=I.fromUrl(t),s=this.createVisit(O({},n,{to:r,hash:i}));this.performNavigation(s,e)}async function Mu(t,e={}){if(this.navigating){if(this.visit.state>=6)return t.state=2,void(this.onVisitEnd=()=>this.performNavigation(t,e));await this.hooks.call("visit:abort",this.visit,void 0),delete this.visit.to.document,this.visit.state=8}this.navigating=!0,this.visit=t;let{el:n}=t.trigger;e.referrer=e.referrer||this.location.url,e.animate===!1&&(t.animation.animate=!1),t.animation.animate||this.classes.clear();let r=e.history||ps(n,"data-swup-history");typeof r=="string"&&["push","replace"].includes(r)&&(t.history.action=r);let i=e.animation||ps(n,"data-swup-animation");var s,o;typeof i=="string"&&(t.animation.name=i),t.meta=e.meta||{},typeof e.cache=="object"?(t.cache.read=(s=e.cache.read)!=null?s:t.cache.read,t.cache.write=(o=e.cache.write)!=null?o:t.cache.write):e.cache!==void 0&&(t.cache={read:!!e.cache,write:!!e.cache}),delete e.cache;try{await this.hooks.call("visit:start",t,void 0),t.state=3;let a=this.hooks.call("page:load",t,{options:e},async(u,c)=>{let d;return u.cache.read&&(d=this.cache.get(u.to.url)),c.page=d||await this.fetchPage(u.to.url,c.options),c.cache=!!d,c.page});a.then(({html:u})=>{t.advance(5),t.to.html=u,t.to.document=new DOMParser().parseFromString(u,"text/html")});let l=t.to.url+t.to.hash;if(t.history.popstate||(t.history.action==="replace"||t.to.url===this.location.url?Le(l):(this.currentHistoryIndex++,Tu(l,{index:this.currentHistoryIndex}))),this.location=I.fromUrl(l),t.history.popstate&&this.classes.add("is-popstate"),t.animation.name&&this.classes.add(`to-${vs(t.animation.name)}`),t.animation.wait&&await a,t.done||(await this.hooks.call("visit:transition",t,void 0,async()=>{if(!t.animation.animate)return await this.hooks.call("animation:skip",void 0),void await this.renderPage(t,await a);t.advance(4),await this.animatePageOut(t),t.animation.native&&document.startViewTransition?await document.startViewTransition(async()=>await this.renderPage(t,await a)).finished:await this.renderPage(t,await a),await this.animatePageIn(t)}),t.done))return;await this.hooks.call("visit:end",t,void 0,()=>this.classes.clear()),t.state=7,this.navigating=!1,this.onVisitEnd&&(this.onVisitEnd(),this.onVisitEnd=void 0)}catch(a){if(!a||a!=null&&a.aborted)return void(t.state=8);t.state=9,console.error(a),this.options.skipPopStateHandling=()=>(window.location.assign(t.to.url+t.to.hash),!0),window.history.back()}finally{delete t.to.document}}var Hu=async function(t){await this.hooks.call("animation:out:start",t,void 0,()=>{this.classes.add("is-changing","is-animating","is-leaving")}),await this.hooks.call("animation:out:await",t,{skip:!1},(e,{skip:n})=>{if(!n)return this.awaitAnimations({selector:e.animation.selector})}),await this.hooks.call("animation:out:end",t,void 0)},Nu=function(t){var e;let n=t.to.document;if(!n)return!1;let r=((e=n.querySelector("title"))==null?void 0:e.innerText)||"";document.title=r;let i=Un('[data-swup-persist]:not([data-swup-persist=""])'),s=t.containers.map(o=>{let a=document.querySelector(o),l=n.querySelector(o);return a&&l?(a.replaceWith(l.cloneNode(!0)),!0):(a||console.warn(`[swup] Container missing in current document: ${o}`),l||console.warn(`[swup] Container missing in incoming document: ${o}`),!1)}).filter(Boolean);return i.forEach(o=>{let a=o.getAttribute("data-swup-persist"),l=Fn(`[data-swup-persist="${a}"]`);l&&l!==o&&l.replaceWith(o)}),s.length===t.containers.length},Du=function(t){let e={behavior:"auto"},{target:n,reset:r}=t.scroll,i=n??t.to.hash,s=!1;return i&&(s=this.hooks.callSync("scroll:anchor",t,{hash:i,options:e},(o,{hash:a,options:l})=>{let u=this.getAnchorElement(a);return u&&u.scrollIntoView(l),!!u})),r&&!s&&(s=this.hooks.callSync("scroll:top",t,{options:e},(o,{options:a})=>(window.scrollTo(O({top:0,left:0},a)),!0))),s},Bu=async function(t){if(t.done)return;let e=this.hooks.call("animation:in:await",t,{skip:!1},(n,{skip:r})=>{if(!r)return this.awaitAnimations({selector:n.animation.selector})});await ys(),await this.hooks.call("animation:in:start",t,void 0,()=>{this.classes.remove("is-animating")}),await e,await this.hooks.call("animation:in:end",t,void 0)},Qu=async function(t,e){if(t.done)return;t.advance(6);let{url:n}=e;this.isSameResolvedUrl(Te(),n)||(Le(n),this.location=I.fromUrl(n),t.to.url=this.location.url,t.to.hash=this.location.hash),await this.hooks.call("content:replace",t,{page:e},(r,{})=>{if(this.classes.remove("is-leaving"),r.animation.animate&&this.classes.add("is-rendering"),!this.replaceContent(r))throw new Error("[swup] Container mismatch, aborting");r.animation.animate&&(this.classes.add("is-changing","is-animating","is-rendering"),r.animation.name&&this.classes.add(`to-${vs(r.animation.name)}`))}),await this.hooks.call("content:scroll",t,void 0,()=>this.scrollToContent(t)),await this.hooks.call("page:view",t,{url:this.location.url,title:document.title})},qu=function(t){var e;if(e=t,Boolean(e?.isSwupPlugin)){if(t.swup=this,!t._checkRequirements||t._checkRequirements())return t._beforeMount&&t._beforeMount(),t.mount(),this.plugins.push(t),this.plugins}else console.error("Not a swup plugin instance",t)};function Fu(t){let e=this.findPlugin(t);if(e)return e.unmount(),e._afterUnmount&&e._afterUnmount(),this.plugins=this.plugins.filter(n=>n!==e),this.plugins;console.error("No such plugin",e)}function Vu(t){return this.plugins.find(e=>e===t||e.name===t||e.name===`Swup${String(t)}`)}function $u(t){if(typeof this.options.resolveUrl!="function")return console.warn("[swup] options.resolveUrl expects a callback function."),t;let e=this.options.resolveUrl(t);return e&&typeof e=="string"?e.startsWith("//")||e.startsWith("http")?(console.warn("[swup] options.resolveUrl needs to return a relative url"),t):e:(console.warn("[swup] options.resolveUrl needs to return a url"),t)}function Uu(t,e){return this.resolveUrl(t)===this.resolveUrl(e)}var ju={animateHistoryBrowsing:!1,animationSelector:'[class*="transition-"]',animationScope:"html",cache:!0,containers:["#swup"],hooks:{},ignoreVisit:(t,{el:e}={})=>!(e==null||!e.closest("[data-no-swup]")),linkSelector:"a[href]",linkToSelf:"scroll",native:!1,plugins:[],resolveUrl:t=>t,requestHeaders:{"X-Requested-With":"swup",Accept:"text/html, application/xhtml+xml"},skipPopStateHandling:t=>{var e;return((e=t.state)==null?void 0:e.source)!=="swup"},timeout:0},Lt=class{get currentPageUrl(){return this.location.url}constructor(e={}){var n,r;this.version="4.8.1",this.options=void 0,this.defaults=ju,this.plugins=[],this.visit=void 0,this.cache=void 0,this.hooks=void 0,this.classes=void 0,this.location=I.fromUrl(window.location.href),this.currentHistoryIndex=void 0,this.clickDelegate=void 0,this.navigating=!1,this.onVisitEnd=void 0,this.use=qu,this.unuse=Fu,this.findPlugin=Vu,this.log=()=>{},this.navigate=Ru,this.performNavigation=Mu,this.createVisit=Iu,this.delegateEvent=_u,this.fetchPage=Pu,this.awaitAnimations=Cu,this.renderPage=Qu,this.replaceContent=Nu,this.animatePageIn=Bu,this.animatePageOut=Hu,this.scrollToContent=Du,this.getAnchorElement=Au,this.getCurrentUrl=Te,this.resolveUrl=$u,this.isSameResolvedUrl=Uu,this.options=O({},this.defaults,e),this.handleLinkClick=this.handleLinkClick.bind(this),this.handlePopState=this.handlePopState.bind(this),this.cache=new qn(this),this.classes=new Vn(this),this.hooks=new $n(this),this.visit=this.createVisit({to:""}),this.currentHistoryIndex=(n=(r=window.history.state)==null?void 0:r.index)!=null?n:1,this.enable()}async enable(){var e;let{linkSelector:n}=this.options;this.clickDelegate=this.delegateEvent(n,"click",this.handleLinkClick),window.addEventListener("popstate",this.handlePopState),this.options.animateHistoryBrowsing&&(window.history.scrollRestoration="manual"),this.options.native=this.options.native&&!!document.startViewTransition,this.options.plugins.forEach(r=>this.use(r));for(let[r,i]of Object.entries(this.options.hooks)){let[s,o]=this.hooks.parseName(r);this.hooks.on(s,i,o)}((e=window.history.state)==null?void 0:e.source)!=="swup"&&Le(null,{index:this.currentHistoryIndex}),await ys(),await this.hooks.call("enable",void 0,void 0,()=>{let r=document.documentElement;r.classList.add("swup-enabled"),r.classList.toggle("swup-native",this.options.native)})}async destroy(){this.clickDelegate.destroy(),window.removeEventListener("popstate",this.handlePopState),this.cache.clear(),this.options.plugins.forEach(e=>this.unuse(e)),await this.hooks.call("disable",void 0,void 0,()=>{let e=document.documentElement;e.classList.remove("swup-enabled"),e.classList.remove("swup-native")}),this.hooks.clear()}shouldIgnoreVisit(e,{el:n,event:r}={}){let{origin:i,url:s,hash:o}=I.fromUrl(e);return i!==window.location.origin||!(!n||!this.triggerWillOpenNewWindow(n))||!!this.options.ignoreVisit(s+o,{el:n,event:r})}handleLinkClick(e){let n=e.delegateTarget,{href:r,url:i,hash:s}=I.fromElement(n);if(this.shouldIgnoreVisit(r,{el:n,event:e}))return;if(this.navigating&&i===this.visit.to.url)return void e.preventDefault();let o=this.createVisit({to:i,hash:s,el:n,event:e});e.metaKey||e.ctrlKey||e.shiftKey||e.altKey?this.hooks.callSync("link:newtab",o,{href:r}):e.button===0&&this.hooks.callSync("link:click",o,{el:n,event:e},()=>{var a;let l=(a=o.from.url)!=null?a:"";e.preventDefault(),i&&i!==l?this.isSameResolvedUrl(i,l)||this.performNavigation(o):s?this.hooks.callSync("link:anchor",o,{hash:s},()=>{Le(i+s),this.scrollToContent(o)}):this.hooks.callSync("link:self",o,void 0,()=>{this.options.linkToSelf==="navigate"?this.performNavigation(o):(Le(i),this.scrollToContent(o))})})}handlePopState(e){var n,r,i,s;let o=(n=(r=e.state)==null?void 0:r.url)!=null?n:window.location.href;if(this.options.skipPopStateHandling(e)||this.isSameResolvedUrl(Te(),this.location.url))return;let{url:a,hash:l}=I.fromUrl(o),u=this.createVisit({to:a,hash:l,event:e});u.history.popstate=!0;let c=(i=(s=e.state)==null?void 0:s.index)!=null?i:0;c&&c!==this.currentHistoryIndex&&(u.history.direction=c-this.currentHistoryIndex>0?"forwards":"backwards",this.currentHistoryIndex=c),u.animation.animate=!1,u.scroll.reset=!1,u.scroll.target=!1,this.options.animateHistoryBrowsing&&(u.animation.animate=!0,u.scroll.reset=!0),this.hooks.callSync("history:popstate",u,{event:e},()=>{this.performNavigation(u)})}triggerWillOpenNewWindow(e){return!!e.matches('[download], [target="_blank"]')}};function _e(){return _e=Object.assign?Object.assign.bind():function(t){for(var e=1;eString(t).split(".").map(e=>String(parseInt(e||"0",10))).concat(["0","0"]).slice(0,3).join("."),ge=class{constructor(){this.isSwupPlugin=!0,this.swup=void 0,this.version=void 0,this.requires={},this.handlersToUnregister=[]}mount(){}unmount(){this.handlersToUnregister.forEach(e=>e()),this.handlersToUnregister=[]}_beforeMount(){if(!this.name)throw new Error("You must define a name of plugin when creating a class.")}_afterUnmount(){}_checkRequirements(){return typeof this.requires!="object"||Object.entries(this.requires).forEach(([e,n])=>{if(!function(r,i,s){let o=function(a,l){var u;if(a==="swup")return(u=l.version)!=null?u:"";{var c;let d=l.findPlugin(a);return(c=d?.version)!=null?c:""}}(r,s);return!!o&&((a,l)=>l.every(u=>{let[,c,d]=u.match(/^([\D]+)?(.*)$/)||[];var h,p;return((g,m)=>{let v={"":w=>w===0,">":w=>w>0,">=":w=>w>=0,"<":w=>w<0,"<=":w=>w<=0};return(v[m]||v[""])(g)})((p=d,h=bs(h=a),p=bs(p),h.localeCompare(p,void 0,{numeric:!0})),c||">=")}))(o,i)}(e,n=Array.isArray(n)?n:[n],this.swup)){let r=`${e} ${n.join(", ")}`;throw new Error(`Plugin version mismatch: ${this.name} requires ${r}`)}}),!0}on(e,n,r={}){var i;n=!(i=n).name.startsWith("bound ")||i.hasOwnProperty("prototype")?n.bind(this):n;let s=this.swup.hooks.on(e,n,r);return this.handlersToUnregister.push(s),s}once(e,n,r={}){return this.on(e,n,_e({},r,{once:!0}))}before(e,n,r={}){return this.on(e,n,_e({},r,{before:!0}))}replace(e,n,r={}){return this.on(e,n,_e({},r,{replace:!0}))}off(e,n){return this.swup.hooks.off(e,n)}};(function(){if(!(typeof window>"u"||typeof document>"u"||typeof HTMLElement>"u")){var t=!1;try{var e=document.createElement("div");e.addEventListener("focus",function(s){s.preventDefault(),s.stopPropagation()},!0),e.focus(Object.defineProperty({},"preventScroll",{get:function(){if(navigator&&typeof navigator.userAgent<"u"&&navigator.userAgent&&navigator.userAgent.match(/Edge\/1[7-8]/))return t=!1;t=!0}}))}catch{}if(HTMLElement.prototype.nativeFocus===void 0&&!t){HTMLElement.prototype.nativeFocus=HTMLElement.prototype.focus;var n=function(s){for(var o=s.parentNode,a=[],l=document.scrollingElement||document.documentElement;o&&o!==l;)(o.offsetHeightn.replace(`{${r}}`,e[r]||""),t||"")}var Wn=class{constructor(){var e;this.id="swup-announcer",this.style="position:absolute;top:0;left:0;clip:rect(0 0 0 0);clip-path:inset(50%);overflow:hidden;white-space:nowrap;word-wrap:normal;width:1px;height:1px;",this.region=void 0,this.region=(e=this.getRegion())!=null?e:this.createRegion()}getRegion(){return document.getElementById(this.id)}createRegion(){let e=function(n){let r=document.createElement("template");return r.innerHTML=n,r.content.children[0]}(`

`);return document.body.appendChild(e),e}announce(e,n=0){return new Promise(r=>{setTimeout(()=>{this.region.textContent===e&&(e=`${e}.`),this.region.textContent="",this.region.textContent=e,r()},n)})}};function xs(t){let e;if(e=typeof t=="string"?document.querySelector(t):t,!(e instanceof HTMLElement))return;let n=e.getAttribute("tabindex");e.setAttribute("tabindex","-1"),e.focus({preventScroll:!0}),n!==null&&e.setAttribute("tabindex",n)}var Tt=class extends ge{constructor(e={}){super(),this.name="SwupA11yPlugin",this.requires={swup:">=4"},this.defaults={headingSelector:"h1",respectReducedMotion:!0,autofocus:!1,announcements:{visit:"Navigated to: {title}",url:"New page at {url}"}},this.options=void 0,this.announcer=void 0,this.announcementDelay=100,this.rootSelector="body",this.handleAnchorScroll=(n,{hash:r})=>{let i=this.swup.getAnchorElement(r);i instanceof HTMLElement&&xs(i)},this.options=jn({},this.defaults,e),this.announcer=new Wn}mount(){this.swup.hooks.create("content:announce"),this.swup.hooks.create("content:focus"),this.before("visit:start",this.prepareVisit),this.on("visit:start",this.markAsBusy),this.on("visit:end",this.unmarkAsBusy),this.on("visit:end",this.focusContent),this.on("visit:end",this.announceContent),this.on("scroll:anchor",this.handleAnchorScroll),this.before("visit:start",this.disableAnimations),this.before("link:self",this.disableAnimations),this.before("link:anchor",this.disableAnimations),this.swup.announce=this.announce.bind(this)}unmount(){this.swup.announce=void 0}async announce(e){await this.announcer.announce(e)}markAsBusy(){document.documentElement.setAttribute("aria-busy","true")}unmarkAsBusy(){document.documentElement.removeAttribute("aria-busy")}prepareVisit(e){e.a11y={announce:void 0,focus:this.rootSelector}}announceContent(e){this.swup.hooks.callSync("content:announce",e,void 0,n=>{n.a11y.announce===void 0&&(n.a11y.announce=this.getPageAnnouncement()),n.a11y.announce&&this.announcer.announce(n.a11y.announce,this.announcementDelay)})}focusContent(e){this.swup.hooks.callSync("content:focus",e,void 0,n=>{n.a11y.focus&&(this.options.autofocus&&function(){let r=function(){let i=document.querySelector("body [autofocus]");if(i&&!i.closest('[inert], [aria-disabled], [aria-hidden="true"]'))return i}();return!!r&&(r!==document.activeElement&&r.focus(),!0)}()===!0||xs(n.a11y.focus))})}getPageAnnouncement(){let{headingSelector:e,announcements:n}=this.options;return function({headingSelector:r="h1",announcements:i={}}){var s,o;let a=document.documentElement.lang||"*",{href:l,url:u,pathname:c}=I.fromUrl(window.location.href),d=(s=(o=i[a])!=null?o:i["*"])!=null?s:i;if(typeof d!="object")return;let h=document.querySelector(r);h||console.warn(`SwupA11yPlugin: No main heading (${r}) found on new page`);let p=h?.getAttribute("aria-label")||h?.textContent||document.title||Es(d.url,{href:l,url:u,path:c});return Es(d.visit,{title:p,href:l,url:u,path:c})}({headingSelector:e,announcements:n})}disableAnimations(e){this.options.respectReducedMotion&&window.matchMedia("(prefers-reduced-motion: reduce)").matches&&(e.animation.animate=!1,e.scroll.animate=!1)}};function zn(){return zn=Object.assign?Object.assign.bind():function(t){for(var e=1;e{let a=Math.random()*this.trickleValue;this.setValue(this.value+a)},e!==void 0&&(this.className=String(e)),n!==void 0&&(this.styleAttr=String(n)),r!==void 0&&(this.animationDuration=Number(r)),i!==void 0&&(this.minValue=Number(i)),s!==void 0&&(this.initialValue=Number(s)),o!==void 0&&(this.trickleValue=Number(o)),this.styleElement=this.createStyleElement(),this.progressElement=this.createProgressElement()}get defaultStyles(){return` - .${this.className} { - position: fixed; - display: block; - top: 0; - left: 0; - width: 100%; - height: 3px; - background-color: black; - z-index: 9999; - transition: - transform ${this.animationDuration}ms ease-out, - opacity ${this.animationDuration/2}ms ${this.animationDuration/2}ms ease-in; - transform: translate3d(0, 0, 0) scaleX(var(--progress, 0)); - transform-origin: 0; - } - `}show(){this.visible||(this.visible=!0,this.installStyleElement(),this.installProgressElement(),this.startTrickling())}hide(){this.visible&&!this.hiding&&(this.hiding=!0,this.fadeProgressElement(()=>{this.uninstallProgressElement(),this.stopTrickling(),this.visible=!1,this.hiding=!1}))}setValue(e){this.value=Math.min(1,Math.max(this.minValue,e)),this.refresh()}installStyleElement(){document.head.prepend(this.styleElement)}installProgressElement(){this.progressElement.style.setProperty("--progress",String(0)),this.progressElement.style.opacity="1",document.body.prepend(this.progressElement),this.progressElement.scrollTop=0,this.setValue(Math.random()*this.initialValue)}fadeProgressElement(e){this.progressElement.style.opacity="0",setTimeout(e,1.5*this.animationDuration)}uninstallProgressElement(){this.progressElement.remove()}startTrickling(){this.trickleInterval||(this.trickleInterval=window.setInterval(this.trickle,this.animationDuration))}stopTrickling(){window.clearInterval(this.trickleInterval),delete this.trickleInterval}refresh(){requestAnimationFrame(()=>{this.progressElement.style.setProperty("--progress",String(this.value))})}createStyleElement(){let e=document.createElement("style");return this.styleAttr.split(" ").forEach(n=>e.setAttribute(n,"")),e.textContent=this.defaultStyles,e}createProgressElement(){let e=document.createElement("div");return e.className=this.className,e.setAttribute("aria-hidden","true"),e}},_t=class extends ge{constructor(e={}){super(),this.name="SwupProgressPlugin",this.defaults={className:"swup-progress-bar",delay:300,transition:300,minValue:.1,initialValue:.25,finishAnimation:!0},this.options=void 0,this.progressBar=void 0,this.showProgressBarTimeout=void 0,this.hideProgressBarTimeout=void 0,this.options=zn({},this.defaults,e);let{className:n,minValue:r,initialValue:i,transition:s}=this.options;this.progressBar=new Gn({className:n,minValue:r,initialValue:i,animationDuration:s})}mount(){this.on("visit:start",this.startShowingProgress),this.on("page:view",this.stopShowingProgress)}startShowingProgress(){this.progressBar.setValue(0),this.showProgressBarAfterDelay()}stopShowingProgress(){this.progressBar.setValue(1),this.options.finishAnimation?this.finishAnimationAndHideProgressBar():this.hideProgressBar()}showProgressBar(){this.cancelHideProgressBarTimeout(),this.progressBar.show()}showProgressBarAfterDelay(){this.cancelShowProgressBarTimeout(),this.cancelHideProgressBarTimeout(),this.showProgressBarTimeout=window.setTimeout(this.showProgressBar.bind(this),this.options.delay)}hideProgressBar(){this.cancelShowProgressBarTimeout(),this.progressBar.hide()}finishAnimationAndHideProgressBar(){this.cancelShowProgressBarTimeout(),this.hideProgressBarTimeout=window.setTimeout(this.hideProgressBar.bind(this),this.options.transition)}cancelShowProgressBarTimeout(){window.clearTimeout(this.showProgressBarTimeout),delete this.showProgressBarTimeout}cancelHideProgressBarTimeout(){window.clearTimeout(this.hideProgressBarTimeout),delete this.hideProgressBarTimeout}};var ks=()=>{window.dispatchEvent(new Event("exdoc:loaded"))},Wu=(t,{page:e})=>{//i.test(e.html)&&(t.abort(),window.location.reload())};window.addEventListener("DOMContentLoaded",ks);!A&&window.location.protocol!=="file:"&&new Lt({animationSelector:!1,containers:["#main"],ignoreVisit:t=>{let e=t.split("#")[0];return e===window.location.pathname||e===window.location.pathname+".html"},linkSelector:'a[href]:not([href^="/"]):not([href^="http"])',hooks:{"page:load":Wu,"page:view":ks},plugins:[new Tt,new _t({delay:500})]});})(); -/*! Bundled license information: - -lunr/lunr.js: - (** - * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9 - * Copyright (C) 2020 Oliver Nightingale - * @license MIT - *) - (*! - * lunr.utils - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.Set - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.tokenizer - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.Pipeline - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.Vector - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.stemmer - * Copyright (C) 2020 Oliver Nightingale - * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt - *) - (*! - * lunr.stopWordFilter - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.trimmer - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.TokenSet - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.Index - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.Builder - * Copyright (C) 2020 Oliver Nightingale - *) -*/ diff --git a/site/dist/html-erlang-DQDXQC7W.css b/site/dist/html-erlang-DQDXQC7W.css deleted file mode 100644 index 2a7bf5fc..00000000 --- a/site/dist/html-erlang-DQDXQC7W.css +++ /dev/null @@ -1,6 +0,0 @@ -:root{--main: hsl(0, 100%, 44%);--mainDark: hsl(0, 100%, 34%);--mainDarkest: hsl(0, 100%, 24%);--mainLight: hsl(0, 100%, 64%);--mainLightest: hsl(0, 100%, 74%);--searchBarFocusColor: hsl(0, 100%, 50%);--searchBarBorderColor: rgb(255, 71, 71, .1);--link-color: hsl(212, 96%, 45%);--link-visited-color: hsl(212, 96%, 40%)}body.dark{--link-color: hsl(212, 56%, 72%);--link-visited-color: hsl(212, 56%, 67%)}@font-face{font-family:Lato;font-style:normal;font-display:swap;font-weight:400;src:url(./lato-latin-ext-400-normal-N27NCBWW.woff2) format("woff2"),url(./lato-all-400-normal-MNITWADU.woff) format("woff");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Lato;font-style:normal;font-display:swap;font-weight:400;src:url(./lato-latin-400-normal-W7754I4D.woff2) format("woff2"),url(./lato-all-400-normal-MNITWADU.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Lato;font-style:normal;font-display:swap;font-weight:700;src:url(./lato-latin-ext-700-normal-Q2L5DVMW.woff2) format("woff2"),url(./lato-all-700-normal-XMT5XFBS.woff) format("woff");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Lato;font-style:normal;font-display:swap;font-weight:700;src:url(./lato-latin-700-normal-2XVSBPG4.woff2) format("woff2"),url(./lato-all-700-normal-XMT5XFBS.woff) format("woff");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}:root{--content-width: 949px;--content-gutter: 60px;--borderRadius-lg: 14px;--borderRadius-base: 8px;--borderRadius-sm: 3px;--navTabBorderWidth: 2px;--sansFontFamily: "Lato", system-ui, Segoe UI, Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";--monoFontFamily: ui-monospace, SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;--baseLineHeight: 1.5em;--gray25: hsl(207, 43%, 98%);--gray50: hsl(207, 43%, 96%);--gray100: hsl(212, 33%, 91%);--gray200: hsl(210, 29%, 88%);--gray300: hsl(210, 26%, 84%);--gray400: hsl(210, 21%, 64%);--gray450: hsl(210, 21%, 49%);--gray500: hsl(210, 21%, 34%);--gray600: hsl(210, 27%, 26%);--gray700: hsl(212, 35%, 17%);--gray750: hsl(214, 46%, 14%);--gray800: hsl(216, 52%, 11%);--gray800-opacity-0: hsla(216, 52%, 11%, 0%);--gray850: hsl(216, 63%, 8%);--gray900: hsl(218, 73%, 4%);--gray900-opacity-50: hsla(218, 73%, 4%, 50%);--gray900-opacity-0: hsla(218, 73%, 4%, 0%);--coldGrayFaint: hsl(240, 5%, 97%);--coldGrayLight: hsl(240, 5%, 88%);--coldGray-lightened-10: hsl(240, 5%, 56%);--coldGray: hsl(240, 5%, 46%);--coldGray-opacity-10: hsla(240, 5%, 46%, 10%);--coldGrayDark: hsl(240, 5%, 28%);--coldGrayDim: hsl(240, 5%, 18%);--yellowLight: hsl(43, 100%, 95%);--yellowDark: hsl(44, 100%, 15%);--yellow: hsl(60, 100%, 43%);--green-lightened-10: hsl(90, 100%, 45%);--green: hsl(90, 100%, 35%);--white: hsl(0, 0%, 100%);--white-opacity-50: hsla(0, 0%, 100%, 50%);--white-opacity-10: hsla(0, 0%, 100%, 10%);--white-opacity-0: hsla(0, 0%, 100%, 0%);--black: hsl(0, 0%, 0%);--black-opacity-10: hsla(0, 0%, 0%, 10%);--black-opacity-50: hsla(0, 0%, 0%, 50%);--orangeDark: hsl(30, 90%, 40%);--orangeLight: hsl(30, 80%, 50%);--text-xs: .75rem;--text-sm: .875rem;--text-md: 1rem;--text-lg: 1.125rem;--text-xl: 1.25rem;--transition-duration: .15s;--transition-timing: cubic-bezier(.4, 0, .2, 1);--transition-all: all var(--transition-duration) var(--transition-timing);--transition-colors: color var(--transition-duration) var(--transition-timing), background-color var(--transition-duration) var(--transition-timing), border-color var(--transition-duration) var(--transition-timing), text-decoration-color var(--transition-duration) var(--transition-timing), fill var(--transition-duration) var(--transition-timing), stroke var(--transition-duration) var(--transition-timing);--transition-opacity: opacity var(--transition-duration) var(--transition-timing)}@media screen and (max-width: 768px){:root{--content-width: 100%;--content-gutter: 20px}}option{background-color:var(--sidebarBackground)}:root{--background: var(--white);--contrast: var(--black);--textBody: var(--gray800);--textHeaders: var(--gray900);--textDetailAccent: var(--mainLight);--textDetailBackground: var(--coldGrayFaint);--iconAction: var(--coldGray);--iconActionHover: var(--gray800);--blockquoteBackground: var(--coldGrayFaint);--blockquoteBorder: var(--coldGrayLight);--tableHeadBorder: var(--gray100);--tableBodyBorder: var(--gray50);--warningBackground: hsl( 33, 100%, 97%);--warningHeadingBackground: hsl( 33, 87%, 64%);--warningHeading: var(--black);--errorBackground: hsl( 7, 81%, 96%);--errorHeadingBackground: hsl( 6, 80%, 60%);--errorHeading: var(--white);--infoBackground: hsl(206, 91%, 96%);--infoHeadingBackground: hsl(213, 92%, 62%);--infoHeading: var(--white);--neutralBackground: hsl(212, 29%, 92%);--neutralHeadingBackground: hsl(220, 43%, 11%);--neutralHeading: var(--white);--tipBackground: hsl(142, 31%, 93%);--tipHeadingBackground: hsl(134, 39%, 36%);--tipHeading: var(--white);--fnSpecAttr: var(--coldGray);--fnDeprecated: var(--yellowLight);--blink: var(--yellowLight);--codeBackground: var(--gray25);--codeBorder: var(--gray100);--codeScrollThumb: var(--gray400);--codeScrollBackground: var(--codeBorder);--admCodeBackground: var(--gray25);--admCodeBorder: var(--gray100);--admCodeColor: var(--black);--admInlineCodeColor: var(--black);--admInlineCodeBackground: var(--gray25);--admInlineCodeBorder: var(--gray100);--tabBorder: var(--gray300);--tabBorderTop: var(--gray100);--tabShadow: var(--gray25);--bottomActionsBtnBorder: var(--black-opacity-10);--bottomActionsBtnTitle: var(--mainDark);--modalBackground: var(--white);--settingsInput: var(--gray500);--settingsInputBackground: var(--white);--settingsInputBorder: var(--gray300);--settingsSectionBorder: var(--gray300);--quickSwitchInput: var(--gray500);--quickSwitchContour: var(--coldGray);--success: var(--green);--progressBarColor: var(--gray400);--sidebarAccentMain: var(--black);--sidebarBackground: var(--gray50);--sidebarHeader: var(--gray100);--sidebarMuted: var(--gray800);--sidebarHover: var(--black);--sidebarStaleVersion: var(--orangeDark);--sidebarSubheadings: var(--gray500);--sidebarItem: var(--black);--sidebarInactiveItemBorder: var(--gray500);--sidebarInactiveItemMarker: var(--gray200);--sidebarLanguageAccentBar: var(--mainDark);--sidebarActiveItem: var(--mainDarkest);--searchBarBorder: var(--gray200);--searchAccentMain: var(--gray600);--searchLanguageAccentBar: var(--main);--searchSearch: var(--white);--autocompleteBorder: rgba(3, 9, 19, .1);--autocompletePreview: var(--gray25);--autocompleteSelected: var(--gray25);--autocompleteHover: var(--gray50);--autocompleteBackground: var(--white);--suggestionBorder: var(--gray200);--autocompleteResults: var(--gray600);--autocompleteResultsBold: var(--gray800);--autocompleteLabelBack: var(--gray100);--autocompleteLabelFont: var(--gray600)}body.dark{--background: var(--gray900);--contrast: var(--white);--textBody: var(--gray200);--textHeaders: var(--gray100);--textDetailAccent: var(--mainLight);--textDetailBackground: var(--gray700);--iconAction: var(--coldGray-lightened-10);--iconActionHover: var(--white);--blockquoteBackground: var(--coldGray-opacity-10);--blockquoteBorder: var(--coldGrayDim);--tableHeadBorder: var(--gray600);--tableBodyBorder: var(--gray700);--warningBackground: hsla( 33, 30%, 60%, 10%);--warningHeadingBackground: hsla( 33, 66%, 35%, 80%);--warningHeading: var(--white);--errorBackground: hsla( 7, 30%, 60%, 10%);--errorHeadingBackground: hsla( 6, 70%, 40%, 80%);--errorHeading: var(--white);--infoBackground: hsla(206, 30%, 60%, 10%);--infoHeadingBackground: hsla(213, 55%, 35%, 80%);--infoHeading: var(--white);--neutralBackground: hsl(210, 30%, 60%, 10%);--neutralHeadingBackground: var(--gray600);--neutralHeading: var(--white);--tipBackground: hsla(142, 30%, 60%, 10%);--tipHeadingBackground: hsla(134, 45%, 30%, 80%);--tipHeading: var(--white);--fnSpecAttr: var(--gray400);--fnDeprecated: var(--yellowDark);--blink: var(--gray600);--codeBackground: var(--gray750);--codeBorder: var(--gray600);--codeScrollThumb: var(--gray500);--codeScrollBackground: var(--codeBorder);--admCodeBackground: var(--gray750);--admCodeBorder: var(--gray600);--admCodeColor: var(--gray100);--admInlineCodeColor: var(--gray100);--admInlineCodeBackground: var(--gray750);--admInlineCodeBorder: var(--gray600);--tabBorder: var(--gray700);--tabBorderTop: var(--gray700);--tabShadow: var(--black);--bottomActionsBtnBorder: var(--white-opacity-10);--bottomActionsBtnTitle: var(--mainLightest);--modalBackground: var(--gray800);--settingsInput: var(--white);--settingsInputBackground: var(--gray700);--settingsInputBorder: var(--gray700);--settingsSectionBorder: var(--gray700);--quickSwitchInput: var(--gray300);--quickSwitchContour: var(--gray500);--success: var(--green-lightened-10);--progressBarColor: var(--gray300);--sidebarAccentMain: var(--gray50);--sidebarBackground: var(--gray800);--sidebarHeader: var(--gray700);--sidebarMuted: var(--gray300);--sidebarHover: var(--white);--sidebarStaleVersion: var(--orangeLight);--sidebarSubheadings: var(--gray400);--sidebarItem: var(--gray200);--sidebarInactiveItemBorder: var(--gray400);--sidebarInactiveItemMarker: var(--gray600);--sidebarLanguageAccentBar: var(--mainLight);--sidebarActiveItem: var(--mainLightest);--searchBarBorder: var(--gray500);--searchAccentMain: var(--gray300);--searchSearch: var(--gray900);--autocompleteBorder: rgba(28,42,60,.75);--autocompletePreview: var(--gray750);--autocompleteSelected: var(--gray750);--autocompleteHover: var(--gray700);--autocompleteBackground: var(--gray800);--suggestionBorder: var(--gray600);--autocompleteResults: var(--gray200);--autocompleteResultsBold: var(--gray100);--autocompleteLabelBack: var(--gray600);--autocompleteLabelFont: rgba(255, 255, 255, .8)}:root:has(body.dark){color-scheme:dark}*,:before,:after{box-sizing:border-box}html{font-family:system-ui,Segoe UI,Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";line-height:1.15;-webkit-text-size-adjust:100%;tab-size:4}body{margin:0}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-color:currentcolor}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}legend{padding:0}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}@font-face{font-family:remixicon;src:url(./remixicon-QPNJX265.woff2) format("woff2");font-display:swap}[class^=ri-],[class*=" ri-"],.remix-icon{font-family:remixicon;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}:root{--icon-arrow-up-s: "\ea78";--icon-arrow-down-s: "\ea4e";--icon-arrow-right-s: "\ea6e";--icon-add: "\ea13";--icon-subtract: "\f1af";--icon-error-warning: "\eca1";--icon-external-link-line: "\ecaf";--icon-information: "\ee59";--icon-alert: "\ea21";--icon-double-quotes-l: "\ec51";--icon-link-m: "\eeaf";--icon-close-line: "\eb99";--icon-code-s-slash-line: "\ebad";--icon-menu-line: "\ef3e";--icon-search-2-line: "\f0cd";--icon-settings-3-line: "\f0e6";--icon-printer-line: "\f029"}.ri-lg{font-size:1.3333em;line-height:.75em;vertical-align:-.0667em}.ri-settings-3-line:before{content:var(--icon-settings-3-line)}.ri-add-line:before{content:var(--icon-add)}.ri-subtract-line:before{content:var(--icon-subtract)}.ri-arrow-up-s-line:before{content:var(--icon-arrow-up-s)}.ri-arrow-down-s-line:before{content:var(--icon-arrow-down-s)}.ri-arrow-right-s-line:before{content:var(--icon-arrow-right-s)}.ri-external-link-line:before{content:var(--icon-external-link-line)}.ri-search-2-line:before{content:var(--icon-search-2-line)}.ri-menu-line:before{content:var(--icon-menu-line)}.ri-close-line:before{content:var(--icon-close-line)}.ri-link-m:before{content:var(--icon-link-m)}.ri-code-s-slash-line:before{content:var(--icon-code-s-slash-line)}.ri-error-warning-line:before{content:var(--icon-error-warning)}.ri-information-line:before{content:var(--icon-information)}.ri-alert-line:before{content:var(--icon-alert)}.ri-double-quotes-l:before{content:var(--icon-double-quotes-l)}.ri-printer-line:before{content:var(--icon-printer-line)}html,body{box-sizing:border-box;height:100%;width:100%}body{--sidebarWidth: 300px;--sidebarMinWidth: 300px;--sidebarTransitionDuration: .3s;background-color:var(--background);color:var(--textBody);font-size:var(--text-md);line-height:1.6875em;outline:none!important}*,*:before,*:after{box-sizing:inherit}.body-wrapper{display:flex;height:100%}.sidebar{display:none;flex-direction:column;width:var(--sidebarWidth);min-width:var(--sidebarMinWidth);max-width:50vw;height:100%;position:fixed;top:0;left:calc(-1 * var(--sidebarWidth));z-index:100;resize:horizontal}.sidebar-button{padding:26px 12px 18px 19px;position:fixed;z-index:200;top:0;left:0;will-change:transform;transform:translate(0)}.content{left:0;width:100%;height:100%;position:absolute}.content .content-inner{container:content / inline-size;max-width:var(--content-width);min-height:100%;margin:0 auto;padding:0 var(--content-gutter) 10px}.content-inner:focus{outline:none}.sidebar-transition .sidebar,.sidebar-transition .sidebar-button,.sidebar-transition .content{transition:all var(--sidebarTransitionDuration) ease-in-out allow-discrete}.sidebar-open .sidebar,.sidebar-transition .sidebar{display:flex}.sidebar-open .sidebar{left:0}.sidebar-open .sidebar-button{transform:translate(calc(var(--sidebarWidth) - 100%))}.sidebar-open .content{width:calc(100% - var(--sidebarWidth));left:var(--sidebarWidth)}@media screen and (max-width: 768px){.sidebar-open .content{left:0;width:100%}.sidebar{max-width:90vw}body:not(.sidebar-open) .sidebar-button{position:absolute}}.swup-progress-bar{height:2px;background-color:var(--progressBarColor)}.sidebar{--sidebarFontSize: 16px;--sidebarLineHeight: 20px;font-family:var(--sansFontFamily);font-size:var(--sidebarFontSize);line-height:var(--sidebarLineHeight);background-color:var(--sidebarBackground);color:var(--sidebarAccentMain);overflow:hidden;& .sidebar-tabpanel{scrollbar-width:thin}}.apple-os .sidebar{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.sidebar ul{list-style:none}.sidebar ul li{margin:0;padding:0 10px}.sidebar a{color:var(--sidebarAccentMain);text-decoration:none;transition:var(--transition-colors)}.sidebar a:hover{color:var(--sidebarHover)}.sidebar .external-link{margin-left:2.5px}.sidebar .sidebar-header{background-color:var(--sidebarHeader);width:100%}.sidebar .sidebar-projectInfo{display:flex;justify-content:start;align-items:center;gap:8px;margin:12px 34px 12px 14px}.sidebar .sidebar-projectInfo>div{flex:1}.sidebar .sidebar-projectImage{align-self:flex-end}.sidebar .sidebar-projectImage img{display:block;max-width:48px;max-height:48px}.sidebar .sidebar-projectName{font-weight:700;font-size:var(--text-xl);line-height:24px;color:var(--sidebarAccentMain);margin:0;padding:0;word-wrap:break-word;display:block;width:calc(100% - 12px)}.sidebar .sidebar-projectVersion{display:block;position:relative;margin:0;padding:0;font-size:var(--sidebarFontSize);line-height:var(--sidebarLineHeight);color:var(--sidebarMuted);width:calc(100% - 12px)}.sidebar .sidebar-projectVersion form{display:flex}.sidebar .sidebar-projectVersion select{cursor:pointer;position:relative;margin:0;padding:0 0 0 10px;border:none;-webkit-appearance:none;appearance:none;background-color:transparent;color:var(--sidebarMuted);z-index:2}.sidebar .sidebar-projectVersion option{color:initial}.sidebar .sidebar-projectVersionsCaret{position:absolute;left:0;top:2px;z-index:1;font-size:8px;color:var(--sidebarMuted)}.sidebar .sidebar-projectVersion select::-ms-expand{display:none}.sidebar .sidebar-staleVersion{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--sidebarStaleVersion)}.sidebar .sidebar-staleVersion>a{color:var(--sidebarStaleVersion);font-weight:400}.sidebar .sidebar-staleIcon{font-size:var(--text-lg);position:relative;top:3px;line-height:0}.sidebar .sidebar-list-nav{display:flex;margin:0;padding:0;overflow:auto;scrollbar-width:thin}.sidebar .sidebar-list-nav :is(li,li button){text-transform:uppercase;letter-spacing:.02em;font-size:var(--text-sm);color:var(--sidebarSubheadings);white-space:nowrap}.sidebar .sidebar-list-nav li{display:inline-block;padding:0}.sidebar .sidebar-list-nav button{background:none;border:0;border-radius:0;-webkit-appearance:none;text-align:inherit;color:inherit;font-weight:inherit;cursor:pointer;display:inline-block;line-height:27px;padding:4px 14px;transition:var(--transition-all)}.sidebar .sidebar-list-nav button{border-bottom:var(--navTabBorderWidth) solid transparent}.sidebar .sidebar-list-nav button:not([aria-selected]):hover{border-bottom:var(--navTabBorderWidth) solid var(--sidebarInactiveItemBorder);color:var(--sidebarAccentMain);transition:var(--transition-all)}.sidebar .sidebar-list-nav button[aria-selected]{border-bottom:var(--navTabBorderWidth) solid var(--sidebarLanguageAccentBar);color:var(--sidebarAccentMain)}.sidebar .sidebar-tabpanel{flex:1 1 .01%;overflow-y:auto;overscroll-behavior:contain;position:relative;-webkit-overflow-scrolling:touch;padding-top:12px;scroll-padding-top:40px}.sidebar .full-list{margin:0;padding:0 0 20px;position:relative}.sidebar .full-list :is(li,a){display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.sidebar .full-list li{padding:0;line-height:27px}.sidebar .full-list li.group{text-transform:uppercase;font-weight:700;font-size:.8em;margin:1.5em 0 0;line-height:1.8em;color:var(--sidebarSubheadings);padding-left:15px}.sidebar .full-list li.nesting-context{font-weight:700;font-size:.9em;line-height:1.8em;color:var(--sidebarSubheadings);margin-top:10px;padding-left:15px}.sidebar .full-list a{margin-right:30px;padding:3px 0 3px 12px;border-left:var(--navTabBorderWidth) solid transparent;color:var(--sidebarItem)}.sidebar .full-list a[aria-selected]{color:var(--sidebarActiveItem)}.sidebar .full-list button{appearance:none;background-color:transparent;border:0;padding:0;cursor:pointer;color:inherit;width:20px;text-align:center;font-size:calc(1.2 * var(--sidebarFontSize));line-height:var(--sidebarLineHeight);position:absolute;display:block;right:10px;transform:translateY(-100%)}.sidebar .full-list a[aria-selected]+button{color:var(--sidebarActiveItem)}.sidebar .full-list button:after{font-family:remixicon;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;content:var(--icon-arrow-down-s)}.sidebar .full-list button[aria-expanded=true]:after{content:var(--icon-arrow-up-s)}.sidebar .full-list ul{display:none;margin:10px 0 10px 10px;padding:0}.sidebar .full-list button[aria-expanded=true]+ul{display:block}.sidebar .full-list>li>a{height:27px;line-height:var(--sidebarLineHeight)}.sidebar .full-list>li>a:hover{border-left-color:var(--sidebarLanguageAccentBar)}.sidebar .full-list>li>a[aria-selected]{border-left-color:var(--sidebarLanguageAccentBar)}.sidebar .full-list>li:last-child{margin-bottom:30px}.sidebar .full-list>li.group:first-child{margin-top:0}.sidebar .full-list>li>ul>li:not(:has(li a[aria-selected=true]))>a[aria-selected=true]:before,.sidebar .full-list>li>ul>li>a:hover:before{content:"\2022";position:absolute;margin-left:-15px;color:var(--sidebarActiveItem)}.sidebar .full-list ul li{line-height:var(--sidebarFontSize);padding:0 8px}.sidebar .full-list ul a{padding-left:15px;height:24px}.sidebar .full-list ul button{font-size:var(--sidebarFontSize)}.sidebar .full-list ul button:after{content:var(--icon-add)}.sidebar .full-list ul button[aria-expanded=true]:after{content:var(--icon-subtract)}.sidebar .full-list ul ul{margin:9px 0 9px 10px}.sidebar .full-list ul ul li{height:20px;color:var(--sidebarAccentMain)}.sidebar .full-list ul ul a{border-left:1px solid var(--sidebarInactiveItemMarker);padding:0 10px;height:20px}.sidebar .full-list ul ul a:hover{border-color:var(--sidebarLanguageAccentBar)}.sidebar .full-list ul ul a[aria-selected]{color:var(--sidebarActiveItem);border-color:var(--sidebarLanguageAccentBar)}.sidebar-button{cursor:pointer;background-color:transparent;border:none;font-size:var(--sidebarFontSize);color:var(--sidebarAccentMain)}.sidebar-button:hover{color:var(--sidebarHover)}body:not(.sidebar-open) .sidebar-button{color:var(--contrast)}@media screen and (max-height: 500px){.sidebar{overflow-y:auto}.sidebar .full-list{overflow:visible}}.top-search{background-color:var(--background);top:0;z-index:99;position:relative;width:100%;padding:10px 0}.search-settings{display:flex;column-gap:12px;align-items:center;width:100%;position:relative}.search-bar{border:1px solid var(--searchBarBorder);border-radius:var(--borderRadius-base);height:48px;position:relative;width:100%}.top-search .search-bar .search-input{background-color:var(--searchSearch);border:1px solid transparent;border-radius:var(--borderRadius-base);color:var(--searchAccentMain);position:relative;height:46px;padding:8px 35px 8px 43px;width:100%;transition:var(--transition-all)}.top-search .search-bar .search-input::placeholder{color:var(--searchAccentMain);opacity:.5}.top-search .search-bar .search-input:focus{border:1px solid var(--searchBarFocusColor);border-radius:calc(var(--borderRadius-base) - 1px);position:relative;box-shadow:0 4px 20px 0 var(--searchBarBorderColor) inset}.top-search .search-bar .search-label{position:relative}.top-search .search-bar .search-button{font-size:var(--text-sm);color:var(--searchAccentMain);background-color:transparent;border:none;cursor:pointer;left:11px;opacity:.5;padding:5px 1px 5px 5px;position:absolute;top:60%;transform:translateY(-60%);z-index:99;transition:var(--transition-all)}.top-search .search-bar.selected .search-button,.top-search .search-bar .search-button:hover,.top-search .search-bar .search-button:focus{color:var(--top-searchLanguageAccentBar);opacity:1}.top-search .search-bar .search-close-button{font-size:var(--text-md);color:var(--searchAccentMain);background-color:transparent;border:none;cursor:pointer;right:11px;margin:0;opacity:.5;padding:5px 1px 5px 0;position:absolute;transform:scaleY(0);top:calc(50% - 13px);transition:var(--transition-all);z-index:99}.top-search .search-bar .search-close-button:hover{opacity:.7}.top-search .search-settings button.icon-settings{display:flex;align-items:center;justify-content:flex-end}.top-search .search-settings .icon-settings{font-size:var(--text-xl);float:right;color:var(--iconAction);text-decoration:none;border:none;transition:color .3s ease-in-out;background-color:transparent;cursor:pointer;padding:0}.top-search .search-settings .icon-settings:hover{color:var(--iconActionHover)}.top-search .search-settings .icon-settings:visited{color:var(--iconAction)}@media screen and (max-width: 768px){.top-search{padding-left:calc(var(--content-gutter) + 36px);padding-right:var(--content-gutter);margin-left:calc(-1 * var(--content-gutter));margin-right:calc(-1 * var(--content-gutter));width:calc(2 * var(--content-gutter) + 100%)}.search-settings{width:100%;box-sizing:border-box}}body.search-focused .search-bar .search-close-button{transform:scaleY(1);transition:var(--transition-all)}@media screen and (hover: hover){body.search-focused .top-search{position:sticky!important}body.search-focused .sidebar-button{position:fixed!important}}@media screen and (hover: none){body.scroll-sticky .top-search{position:sticky!important}body.scroll-sticky .sidebar-button{position:fixed!important}}*:focus,button:focus,[type=button]:focus,[type=reset]:focus,[type=submit]:focus{outline:2px solid var(--main);outline-offset:-2px}*:focus:not(:focus-visible),button:focus:not(:focus-visible),[type=button]:focus:not(:focus-visible),[type=reset]:focus:not(:focus-visible),[type=submit]:focus:not(:focus-visible){outline:0}input[type=text],input[type=number],input[type=date],input[type=datetime],input[type=datetime-local],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=time],input[type=url],input[type=week],textarea{outline:0}.content-inner{font-size:1em;line-height:1.6875em;position:relative;background-color:var(--background);color:var(--textBody)}.content-inner .heading-with-actions{display:flex;flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:6px}.content-inner .heading-with-actions>*:not(h1){flex-shrink:0}.content-inner .heading-with-actions h1{flex-grow:1;justify-self:flex-start;max-width:100%;margin:0;overflow-wrap:break-word}.content-inner .heading-with-actions .icon-action{width:20px;height:20px;display:flex;justify-content:center;align-items:center;font-weight:400}.content-inner .heading-with-actions.top-heading .icon-action{font-size:1.2rem}@container content (width > 600px){.content-inner .heading-with-actions.top-heading{flex-wrap:nowrap;align-items:flex-start;& h1{padding-right:32px}& .icon-action{padding-top:1.7rem}}}.content-inner .top-heading{padding-top:1rem}.content-inner :is(h1,h2,h3,h4,h5,h6){font-family:var(--sansFontFamily);font-weight:700;line-height:1.5em;word-wrap:break-word;color:var(--textHeaders)}.content-inner h1{font-size:2em;margin:.5em 0}.content-inner h1.section-heading{margin:1.5em 0 .5em}.content-inner h1 small{font-weight:400}.content-inner h2{font-size:1.6em;padding-top:1em;margin-bottom:.5em}.content-inner h3{font-size:1.375em;margin:1em 0 .5em}.content-inner li+li{margin-top:.25em}.content-inner :is(a,.a-main){color:var(--link-color);text-decoration:underline;text-decoration-skip-ink:auto}.content-inner :is(a:visited,.a-main:visited){color:var(--link-visited-color)}.content-inner .icon-action{color:var(--iconAction);text-decoration:none;border:none;transition:var(--transition-colors);background-color:transparent;cursor:pointer}.content-inner .icon-action:hover{color:var(--iconActionHover)}.content-inner .icon-action:visited{color:var(--iconAction)}.content-inner .livebook-badge-container{display:flex}.content-inner a.livebook-badge{display:inline-flex}.content-inner .note{color:var(--iconAction);font-size:var(--text-xs);font-weight:400}.content-inner blockquote,.content-inner section.admonition{border-left:3px solid var(--blockquoteBorder);position:relative;margin:1.5625em 0;padding:0 1.2rem;overflow:auto;background-color:var(--blockquoteBackground);border-radius:var(--borderRadius-base)}.content-inner blockquote p:last-child,.content-inner section.admonition p:last-child{padding-bottom:1em;margin-bottom:0}.content-inner table{margin:2em 0;border-collapse:collapse;display:block;overflow:auto}.content-inner th{text-align:left;font-family:var(--sansFontFamily);font-weight:700;padding-bottom:.5em;white-space:nowrap}.content-inner thead tr{border-bottom:1px solid var(--tableHeadBorder)}.content-inner tbody tr{border-bottom:1px solid var(--tableBodyBorder)}.content-inner tbody tr:last-child{border-bottom:none}.content-inner tr{vertical-align:bottom;height:2.5em}.content-inner :is(td,th){padding:.25em .25em .25em 1em;line-height:2em;vertical-align:top}.content-inner .section-heading{--icon-size: 16px;--icon-spacing: 5px;display:grid;grid-template:1fr / 1fr}@media screen and (max-width: 768px){.content-inner .section-heading{--icon-spacing: 2px}}.content-inner .section-heading>:is(.hover-link,.text){grid-row:1;grid-column:1}.content-inner .section-heading .hover-link{text-decoration:none}.content-inner .section-heading i{font-size:var(--icon-size);color:var(--mainLight);top:-2px;margin-left:calc(-1 * (var(--icon-size) + var(--icon-spacing)));padding-right:var(--icon-spacing);position:relative;opacity:0}.content-inner :is(blockquote,section.admonition) .section-heading i{display:none}.content-inner .section-heading:is(:hover,:focus,:target) i{opacity:1}.content-inner .app-vsn{display:none!important;font-size:.6em;line-height:1.5em}@media screen and (max-width: 768px){.content-inner .app-vsn{display:block!important}}.content-inner img{max-width:100%}.content-inner strong>code{font-weight:700}.content-inner code{font-family:var(--monoFontFamily);font-style:normal;line-height:24px;font-weight:400;font-size:var(--text-sm)}@media screen and (max-width: 768px){.content-inner :is(ol,ul){padding-left:calc(1.5 * var(--content-gutter))}}.content-inner section.admonition{border-radius:var(--borderRadius-base);border-left:0}.content-inner section.admonition.warning{background-color:var(--warningBackground)}.content-inner section.admonition.error{background-color:var(--errorBackground)}.content-inner section.admonition.info{background-color:var(--infoBackground)}.content-inner section.admonition.neutral{background-color:var(--neutralBackground)}.content-inner section.admonition.tip{background-color:var(--tipBackground)}.content-inner section.admonition>.admonition-title{color:var(--contrast);margin:0 -1.2rem;padding:.7rem 1.2rem .7rem 3.3rem;font-weight:700;font-style:normal}.content-inner section.admonition>.admonition-title:before{color:var(--contrast);position:absolute;left:1rem;font-size:1.8rem;font-family:remixicon;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.content-inner section.admonition>.admonition-title.warning{background-color:var(--warningHeadingBackground);color:var(--warningHeading)}.content-inner section.admonition>.admonition-title.warning:before{content:var(--icon-error-warning);color:var(--warningHeading)}.content-inner section.admonition>.admonition-title.error{background-color:var(--errorHeadingBackground);color:var(--errorHeading)}.content-inner section.admonition>.admonition-title.error:before{content:var(--icon-error-warning);color:var(--errorHeading)}.content-inner section.admonition>.admonition-title.info{background-color:var(--infoHeadingBackground);color:var(--infoHeading)}.content-inner section.admonition>.admonition-title.info:before{content:var(--icon-information);color:var(--infoHeading)}.content-inner section.admonition>.admonition-title.neutral{background-color:var(--neutralHeadingBackground);color:var(--neutralHeading)}.content-inner section.admonition>.admonition-title.neutral:before{content:var(--icon-double-quotes-l);color:var(--neutralHeading)}.content-inner section.admonition>.admonition-title.tip{background-color:var(--tipHeadingBackground);color:var(--tipHeading)}.content-inner section.admonition>.admonition-title.tip:before{content:var(--icon-information);color:var(--tipHeading)}.content-inner section.admonition>.admonition-title code{margin:0 .5ch}.content-inner section.admonition code{background-color:var(--admInlineCodeBackground);border:1px solid var(--admInlineCodeBorder);color:var(--admInlineCodeColor)}.content-inner section.admonition pre code{background-color:var(--admCodeBackground);border:1px solid var(--admCodeBorder);color:var(--admCodeColor)}.content-inner section.admonition>.admonition-title :is(a,a:visited){color:inherit;text-decoration-color:currentColor}@media screen and (max-width: 768px){.content-inner section.admonition{margin-left:calc(-1 * var(--content-gutter));margin-right:calc(-1 * var(--content-gutter));padding-left:var(--content-gutter);padding-right:var(--content-gutter);border-radius:0}.content-inner section.admonition>.admonition-title{margin:0 calc(-1 * var(--content-gutter))}}.content-inner .summary h2 a{text-decoration:none;border:none;color:var(--textHeaders)!important}.content-inner .summary span.deprecated{color:var(--darkDeprecated);font-weight:400}.content-inner .summary .summary-row .summary-signature{font-family:var(--monoFontFamily);font-size:13px;font-weight:700}.content-inner .summary .summary-row .summary-signature a{text-decoration:none;border:none}.content-inner .summary .summary-row .summary-synopsis{padding:0 1.2em;margin:0 0 .5em}.content-inner .summary .summary-row .summary-synopsis p{margin:0;padding:0}@font-face{font-family:Consolas;src:local("Consolas");size-adjust:110%}.content-inner.content-inner :is(a:has(code,img),pre a){color:var(--link-color);text-shadow:none;text-decoration:none;background-image:none}.content-inner.content-inner :is(a:has(code,img),pre a):is(:visited,:active,:focus,:hover){color:var(--link-visited-color)}.content-inner code{background-color:var(--codeBackground);vertical-align:baseline;border-radius:var(--borderRadius-sm);padding:.1em .2em;border:1px solid var(--codeBorder);text-transform:none}.content-inner code.inline{border-radius:var(--borderRadius-sm);word-wrap:break-word}.content-inner pre{margin:var(--baseLineHeight) 0}.content-inner pre code{display:block;overflow-x:auto;white-space:inherit;padding:1em;scrollbar-width:thin}.content-inner pre code.output{margin:0 12px;max-height:400px;overflow:auto}.content-inner pre code.output+.copy-button{margin-right:12px}.content-inner pre code.output:before{content:"Output";display:block;position:absolute;top:-16px;left:12px;padding:2px 4px;font-size:var(--text-xs);font-family:var(--monoFontFamily);line-height:1;color:var(--textHeaders);background-color:var(--codeBackground);border:1px solid var(--codeBorder);border-bottom:0;border-radius:2px}@media screen and (max-width: 768px){.content-inner>pre:has(code),.content-inner section>pre:has(code){margin-left:calc(-1 * var(--content-gutter));margin-right:calc(-1 * var(--content-gutter))}.content-inner>pre code,.content-inner section>pre code{padding-left:var(--content-gutter);padding-right:var(--content-gutter);border-radius:0;border-left-width:0;border-right-width:0}}@keyframes blink-background{0%,to{background-color:var(--textDetailBackground)}50%{background-color:var(--blink)}}.content-inner .detail:target .detail-header{animation-duration:.55s;animation-name:blink-background;animation-iteration-count:1;animation-timing-function:ease-in-out}.content-inner .detail-header{margin:1em 0;padding:.5em .85em .5em 1em;background-color:var(--textDetailBackground);border-left:3px solid var(--textDetailAccent);font-size:1em;font-family:var(--monoFontFamily);position:relative}.content-inner .detail-header .signature{font-family:var(--monoFontFamily);font-size:13px;font-weight:700;line-height:2em}.content-inner .detail-header:hover a.detail-link,.content-inner .detail-header a.detail-link:focus{opacity:1;text-decoration:none}.content-inner .detail-header a.detail-link{transition:var(--transition-opacity);position:absolute;top:0;left:0;display:block;opacity:0;padding:.6em;line-height:1.5em;margin-left:-2.5em;text-decoration:none;border:none}@media screen and (max-width: 768px){.content-inner .detail-header a.detail-link{margin-left:-30px}}.content-inner .specs pre{font-family:var(--monoFontFamily);font-size:var(--text-xs);font-style:normal;line-height:24px;white-space:pre-wrap;margin:0;padding:0}.content-inner .specs .attribute{color:var(--fnSpecAttr)}.content-inner .docstring{margin:1.2em 0 3em 1.2em}@media screen and (max-width: 768px){.content-inner .docstring{margin-left:0}}.content-inner .docstring:is(h2,h3,h4,h5){font-weight:700}.content-inner .docstring h2{font-size:1.1em}.content-inner .docstring h3{font-size:1em}.content-inner .docstring h4{font-size:.95em}.content-inner .docstring h5{font-size:.9em}.content-inner div.deprecated{display:block;padding:1em;background-color:var(--fnDeprecated);border-radius:var(--borderRadius-sm);margin:var(--baseLineHeight) 0}.content-inner .footer{margin:4em auto 1em;text-align:center;font-size:var(--text-sm)}.content-inner .footer .line{display:inline-block}.content-inner .footer .footer-button{background-color:transparent;border:0;cursor:pointer;padding:0 4px}.content-inner .footer .footer-hex-package{margin-right:4px}.content-inner .bottom-actions{display:flex;justify-content:space-between;margin-top:4em;gap:12px}.bottom-actions-item{flex:1 1 0%}.content-inner .bottom-actions .bottom-actions-button{display:flex;text-decoration:none;flex-direction:column;border-radius:var(--borderRadius-sm);border:1px solid var(--bottomActionsBtnBorder);padding:12px 16px;min-width:150px;transition:var(--transition-all)}.content-inner .bottom-actions .bottom-actions-button:hover{border-color:var(--mainLight)}.content-inner .bottom-actions .bottom-actions-button .subheader{font-size:.8em;color:var(--textHeaders);white-space:nowrap}.content-inner .bottom-actions .bottom-actions-button .title{color:var(--bottomActionsBtnTitle)}.content-inner .bottom-actions .bottom-actions-button[rel=prev]{text-align:start}.content-inner .bottom-actions .bottom-actions-button[rel=next]{text-align:end}@media screen and (max-width: 768px){.content-inner .bottom-actions{flex-direction:column-reverse}}.page-cheatmd .content-inner{--horizontal-space: 1.5em;--vertical-space: 1em}@media (max-width: 600px){.page-cheatmd .content-inner{--horizontal-space: 1em;--vertical-space: .75em}}.page-cheatmd .content-inner{max-width:1200px}.page-cheatmd .content-inner h1{margin-bottom:var(--vertical-space)}.page-cheatmd .content-inner h2{margin:var(--vertical-space) 0;column-span:all;color:var(--gray700);font-weight:500}.dark .page-cheatmd .content-inner h2{color:var(--gray200)}.page-cheatmd .content-inner h3{margin:0 0 1em;font-weight:400}.page-cheatmd .content-inner section.h3{min-width:300px;margin:0;padding:0 0 calc(var(--vertical-space) * 2) 0;break-inside:avoid}.page-cheatmd .content-inner h3 .text{overflow:hidden}.page-cheatmd .content-inner h3 .text:after{content:"";margin-left:calc(var(--horizontal-space) / 2);vertical-align:baseline;display:inline-block;width:100%;height:1px;margin-right:-100%;margin-bottom:5px;background-color:var(--codeBorder)}.page-cheatmd .content-inner h4{display:block;margin:0;padding:.25em var(--horizontal-space);font-weight:400;background:var(--gray100);color:#567;border:solid 1px 1px 0 1px var(--gray100)}.dark .page-cheatmd .content-inner h4{background:#192f50;color:var(--textBody);border:1px solid #192f50;border-bottom:0}.page-cheatmd .content-inner .h2 p{margin:0;display:block;background:var(--gray50);padding:var(--vertical-space) var(--horizontal-space)}.dark .page-cheatmd .content-inner .h2 p{background:var(--gray700)}.page-cheatmd .content-inner .h2 p>code{color:#eb5757;border-radius:var(--borderRadius-sm);padding:.2em .4em}.page-cheatmd .content-inner pre code{padding:var(--vertical-space) var(--horizontal-space)}.page-cheatmd .content-inner .h2 pre{margin:0}.page-cheatmd .content-inner .h2 pre+pre{margin-top:-1px}.page-cheatmd .content-inner pre.wrap{white-space:break-spaces}@media screen and (max-width: 768px){.page-cheatmd .content-inner pre code{border-left-width:1px!important;border-right-width:1px!important}}.page-cheatmd .content-inner .h2 table{display:table;box-sizing:border-box;width:100%;border-collapse:collapse;margin:0}.page-cheatmd .content-inner .h2 th{padding:var(--vertical-space) var(--horizontal-space);line-height:inherit;margin-bottom:-1px;vertical-align:middle;border-bottom:1px solid var(--codeBorder)}.page-cheatmd .content-inner .h2 td{padding:var(--vertical-space) var(--horizontal-space);border:0;border-bottom:1px solid var(--codeBorder)}.page-cheatmd .content-inner .h2 tr:first-child{border-top:1px solid var(--codeBorder)}.page-cheatmd .content-inner .h2 td code{color:#eb5757;border-radius:var(--borderRadius-sm);padding:.2em .4em}.page-cheatmd .content-inner .h2 thead{background-color:var(--gray50)}.dark .page-cheatmd .content-inner .h2 thead{background-color:var(--gray700)}.page-cheatmd .content-inner .h2 tbody{background-color:var(--codeBackground)}.page-cheatmd .content-inner .h2 :is(ul,ol){margin:0;padding:0}.page-cheatmd .content-inner .h2 li{list-style-position:inside;padding:.5em var(--horizontal-space);line-height:2em;vertical-align:middle;background-color:var(--codeBackground);border-bottom:1px solid var(--codeBorder);margin-top:0}.page-cheatmd .content-inner .h2 :is(ul,ol)+pre code{border-top:0}.page-cheatmd .content-inner .h2 li>code{color:#eb5757;border-radius:var(--borderRadius-sm);padding:.2em .4em}.page-cheatmd .content-inner section.width-50{display:block;width:50%;margin:0}.page-cheatmd .content-inner section.width-50>section>table{width:100%}.page-cheatmd .content-inner section:is(.col-2,.col-2-left,.col-3){column-gap:40px}.page-cheatmd .content-inner section.col-2{column-count:2;height:auto}.page-cheatmd .content-inner section.col-2-left{display:grid;grid-template-columns:calc(100% / 3) auto}.page-cheatmd .content-inner section.col-2-left>h2{grid-column-end:span 2}.page-cheatmd .content-inner section.col-3{column-count:3;height:auto}.page-cheatmd .content-inner section.list-4>ul{display:flex;flex-wrap:wrap}.page-cheatmd .content-inner section.list-4>ul>li{flex:0 0 25%}.page-cheatmd .content-inner section.list-6>ul{display:flex;flex-wrap:wrap}.page-cheatmd .content-inner section.list-6>ul>li{flex:0 0 calc(100% / 6)}@media screen and (max-width: 1400px){.page-cheatmd .content-inner section.col-3{column-count:2}.page-cheatmd .content-inner section.col-2-left{display:flex;flex-direction:column}}@media screen and (max-width: 1200px){.page-cheatmd .content-inner section:is(.col-2,.col-3){display:flex;flex-direction:column}.page-cheatmd .content-inner section.list-6>ul>li{flex:0 0 25%}}@media screen and (max-width: 1000px){.page-cheatmd .content-inner section:is(.list-4,.list-6)>ul>li{flex:0 0 calc(100% / 3)}}@media screen and (max-width: 600px){.page-cheatmd .content-inner section:is(.list-4,.list-6)>ul>li{flex:0 0 50%}.page-cheatmd .content-inner section.width-50{width:100%}}#search{min-height:200px;position:relative}#search .loading{height:64px;width:64px;position:absolute;top:50%;left:calc(50% - 32px)}#search .loading div{box-sizing:border-box;display:block;position:absolute;width:51px;height:51px;margin:6px;border:6px solid var(--coldGray);border-radius:50%;animation:loading 1.2s cubic-bezier(.5,0,.5,1) infinite;border-color:var(--coldGray) transparent transparent transparent}#search .loading div:nth-child(1){animation-delay:-.45s}#search .loading div:nth-child(2){animation-delay:-.3s}#search .loading div:nth-child(3){animation-delay:-.15s}@keyframes loading{0%{transform:rotate(0)}to{transform:rotate(360deg)}}#search .result{margin:2em 0 2.5em}#search .result p{margin:0}#search .result-id{font-size:1.4em;margin:0}#search .result-id a{text-decoration:none;color:var(--textHeaders);transition:var(--transition-colors)}#search .result-id a:is(:visited,:active){color:var(--textHeaders)}#search .result-id a:is(:hover,:focus){color:var(--main)}#search :is(.result-id,.result-elem) em{font-style:normal;color:var(--main)}#search .result-id small{font-weight:400}@keyframes keyboard-shortcuts-show{0%{opacity:0}to{opacity:1}}.modal{animation-duration:.15s;animation-name:keyboard-shortcuts-show;animation-iteration-count:1;animation-timing-function:ease-in-out;display:none;background-color:#000000bf;position:fixed;inset:0;z-index:300}.modal.shown{display:block}.modal .modal-contents{margin:75px auto 0;max-width:500px;background-color:var(--modalBackground);border-radius:var(--borderRadius-sm);box-shadow:2px 2px 8px #0003;padding:25px 35px 35px}@media screen and (max-width: 768px){.modal .modal-contents{padding:20px}}.modal .modal-header{display:flex;align-items:start}.modal .modal-title{display:inline-block;flex-grow:1;font-size:1.2rem;font-weight:700;margin-bottom:20px}.modal .modal-title button{border:none;background-color:transparent;color:var(--textHeaders);font-weight:700;margin-right:30px;padding-left:0;text-align:left;transition:var(--transition-colors)}.modal .modal-title button:hover{color:var(--main);cursor:pointer}.modal .modal-title button.active{color:var(--main)}.modal .modal-close{cursor:pointer;display:block;font-size:1.5rem;margin:-8px -8px 0 0;padding:8px;opacity:.7;background-color:transparent;color:var(--textHeaders);border:none;transition:var(--transition-opacity)}.modal .modal-close:hover{opacity:1}#keyboard-shortcuts-content dl.shortcut-row{display:flex;align-items:center;justify-content:space-between;margin:0;padding:6px 0 8px;border-bottom:1px solid var(--settingsSectionBorder)}#keyboard-shortcuts-content dl.shortcut-row:last-of-type{border-bottom-style:none}#keyboard-shortcuts-content dl.shortcut-row:first-child{padding-top:0}#keyboard-shortcuts-content :is(.shortcut-keys,.shortcut-description){display:inline-block}#keyboard-shortcuts-content kbd>kbd{background-color:var(--settingsInputBorder);color:var(--contrast);border-radius:var(--borderRadius-sm);font-family:inherit;font-weight:700;display:inline-block;line-height:1;padding:4px 7px 6px;min-width:26px;text-align:center;font-size:var(--text-sm)}#keyboard-shortcuts-content :is(.shortcut-keys,.shortcut-description){margin:0}#quick-switch-modal-body{width:100%;position:relative}#quick-switch-modal-body .ri-search-2-line{position:absolute;left:0;top:0;padding:4px 10px;color:var(--quickSwitchContour);font-weight:700}#quick-switch-modal-body #quick-switch-input{width:100%;padding:8px 6px 8px 38px;border:none;color:var(--quickSwitchInput);background-color:transparent;border-bottom:1px solid var(--quickSwitchContour);box-sizing:border-box;transition:all .12s ease-out}#quick-switch-modal-body #quick-switch-results{margin:0}#quick-switch-modal-body .quick-switch-result{padding:2px 5px;border-bottom:1px dotted var(--quickSwitchContour);transition:all .12s ease-out}#quick-switch-modal-body .quick-switch-result:last-child{border-bottom:none}#quick-switch-modal-body .quick-switch-result:hover{cursor:pointer}#quick-switch-modal-body .quick-switch-result:is(:hover,.selected){border-left:4px solid var(--main);background-color:var(--codeBackground)}.autocomplete{display:none;position:absolute;width:calc(100% - 32px);top:55px}.autocomplete .triangle{width:0;height:0;border-left:12px solid transparent;border-right:12px solid transparent;border-bottom:12px solid var(--autocompleteBackground);position:absolute;top:8px;left:26px;transform:translate(-50%);z-index:100;background-color:transparent}.autocomplete-preview{width:100%;margin:0;height:100%;line-height:20px;background-color:var(--background);font-family:var(--sansFontFamily);border:4px solid var(--autocompleteBorder);padding:12px 16px}.autocomplete-preview div,.autocomplete-preview span{display:none}.autocomplete-preview.loading div{float:left;display:block;border:5px solid var(--autocompleteBorder);border-radius:50%;border-top:5px solid var(--textDetailAccent);width:20px;height:20px;animation:spinner 4s linear infinite}.autocomplete-preview.loading span{color:var(--autocompleteResults);display:inline;margin-left:6px}.autocomplete-preview.loading span:after{color:var(--autocompleteResults);content:"Loading"}@keyframes spinner{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.autocomplete-preview.loading iframe{height:0}.autocomplete-preview iframe{width:100%;height:100%;border:0}.autocomplete-results{list-style:none;margin:0;padding:15px 20px;display:flex;flex-wrap:wrap;justify-content:space-between;gap:8px;color:var(--autocompleteResults);font-family:var(--sansFontFamily);font-weight:300;font-size:.9rem}.autocomplete-results .query{margin-right:auto}.autocomplete-results .bold{color:var(--autocompleteResultsBold);font-weight:400}.autocomplete.shown{display:block}.autocomplete-container{position:absolute;top:15px;width:100%;z-index:200}.autocomplete-suggestions{background-color:var(--autocompleteBackground);border-radius:var(--borderRadius-base);box-shadow:0 15px 99px 0 var(--autocompleteBorder);overflow-y:auto;max-height:450px;white-space:normal;overflow-x:hidden;overscroll-behavior-y:contain;scrollbar-width:thin}.autocomplete-suggestions.previewing:has(.selected){max-height:80vh}.autocomplete-suggestions.previewing:has(.selected) .autocomplete-suggestion:not(.selected){display:none}.autocomplete-suggestions.previewing:not(:has(.selected)) .autocomplete-preview{display:none}.autocomplete-suggestions:not(.previewing) .autocomplete-preview{display:none}.autocomplete-suggestion{color:var(--textHeaders)!important;display:block;padding:12px 20px;text-decoration:none!important;transition:var(--transition-colors);border-top:1px solid var(--suggestionBorder);font-size:.9rem}.autocomplete-suggestion.selected{background-color:var(--autocompleteSelected);box-shadow:inset 2px 0 var(--main)}.autocomplete-suggestion:hover{background-color:var(--autocompleteHover)}.autocomplete-suggestion:not(.selected) .autocomplete-preview-indicator{display:none}.autocomplete-preview-indicator{float:right}.autocomplete-preview-indicator button{color:var(--iconAction);display:flex;align-items:center;text-decoration:none;border:1px solid var(--suggestionBorder);border-radius:var(--borderRadius-base);transition:var(--transition-colors);background-color:var(--autocompletePreview);cursor:pointer;padding:4px 8px;font-size:var(--text-sm)}.autocomplete-preview-indicator button:hover{color:var(--iconActionHover);background-color:var(--autocompleteHover)}.autocomplete-preview-indicator button i{margin-right:4px}.autocomplete-suggestions.previewing .autocomplete-preview-indicator-closed{display:none}.autocomplete-suggestions:not(.previewing) .autocomplete-preview-indicator-open{display:none}.autocomplete-suggestion:hover:not(.selected) .autocomplete-preview-indicator-closed{display:block}.autocomplete-suggestion em{font-style:normal;font-weight:700}.autocomplete-suggestion .description{opacity:.6;padding-top:3px}.autocomplete-suggestion .label{background-color:var(--autocompleteLabelBack);opacity:.6;color:var(--autocompleteLabelFont);padding:4px 8px;border-radius:4px;margin-left:5px;text-transform:uppercase;font-family:var(--sansFontFamily);font-size:.7rem}.autocomplete-suggestion .header{margin-right:5px}.autocomplete-suggestion .title,.autocomplete-suggestion .description{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:100%}@media screen and (hover: none){.autocomplete-preview-indicator,.autocomplete-results .press-return{display:none!important}}.tooltip{box-shadow:0 0 10px var(--black-opacity-10);max-height:300px;max-width:500px;padding:0;position:absolute;pointer-events:none;margin:0;z-index:99;top:0;left:0;visibility:hidden;transform:translateY(20px);opacity:0;transition:.2s visibility ease-out,.2s transform ease-out,.2s opacity ease-out}.tooltip.tooltip-shown{visibility:visible;transform:translateY(0);opacity:1}.tooltip .tooltip-body{border:1px solid var(--codeBorder);border-radius:var(--borderRadius-sm);overflow:auto}.tooltip .tooltip-body .signature{min-width:320px;width:100%;line-height:1em}.tooltip .tooltip-body .detail-header{border-left:0;margin-bottom:0;margin-top:0}.tooltip .tooltip-body .docstring{background-color:var(--background);padding:1.2em;margin:0;width:498px}.tooltip .tooltip-body .docstring-plain{max-width:498px;width:auto}.tooltip .tooltip-body .version-info{float:right;font-family:var(--monoFontFamily);font-weight:400;opacity:.3;padding-left:.3em}pre{position:relative}pre:hover .copy-button,pre .copy-button:focus{opacity:1}.copy-button{display:flex;opacity:0;position:absolute;top:7px;right:8px;padding:8px;background-color:transparent;backdrop-filter:blur(8px);border-radius:var(--borderRadius-sm);border:1px solid var(--codeBorder);cursor:pointer;transition:var(--transition-all);font-size:var(--text-sm);line-height:24px;color:currentColor;& svg[aria-live=polite]{display:none}}.copy-button svg{opacity:.5;transition:var(--transition-all)}pre .copy-button:hover svg,pre .copy-button:focus-visible svg{opacity:1}.copy-button svg{width:20px}.copy-button.clicked{opacity:1;color:var(--success);& svg[aria-live=polite]{display:block}}.copy-button.clicked svg{display:none;color:currentColor}#settings-modal-content{margin-top:10px}#settings-modal-content .hidden{display:none}#settings-modal-content .input{box-sizing:border-box;width:80%;padding:8px;font-size:var(--text-sm);background-color:var(--settingsInputBackground);color:var(--settingsInput);border:1px solid var(--settingsInputBorder);border-radius:var(--borderRadius-base);transition:var(--transition-all)}#settings-modal-content .input:focus{border-color:var(--main)}#settings-modal-content .input::placeholder{color:var(--gray400)}#settings-modal-content .switch-button-container{display:flex;align-items:center;justify-content:space-between;border-top:1px solid var(--settingsSectionBorder);padding:10px 0}#settings-modal-content .switch-button-container:first-of-type{border-top-style:none;padding-top:0}#settings-modal-content .switch-button-container>div>span{font-size:var(--text-md)}#settings-modal-content .switch-button-container>div>p{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:var(--text-sm);line-height:1.4;margin:0;padding-bottom:6px;padding-right:10px}#settings-modal-content .switch-button{position:relative;display:inline-block;flex-shrink:0;width:40px;height:20px;user-select:none;transition:var(--transition-all)}#settings-modal-content .switch-button__checkbox{appearance:none;position:absolute;display:block;width:20px;height:20px;border-radius:1000px;background-color:#91a4b7;border:3px solid #e5edf5;cursor:pointer;transition:var(--transition-all)}#settings-modal-content .switch-button__bg{display:block;width:100%;height:100%;border-radius:1000px;background-color:#e5edf5;cursor:pointer;transition:var(--transition-all)}#settings-modal-content .switch-button__checkbox:checked{background-color:#fff;border-color:var(--main);transform:translate(100%)}#settings-modal-content .switch-button__checkbox:checked+.switch-button__bg{background-color:var(--main)}#settings-modal-content .switch-button__checkbox:focus{outline:0}#settings-modal-content .switch-button__checkbox:focus+.switch-button__bg{outline:2px solid var(--main);outline-offset:2px}#settings-modal-content .switch-button__checkbox:focus:not(:focus-visible)+.switch-button__bg{outline:0}#settings-modal-content .settings-select{cursor:pointer;position:relative;border:none;background-color:transparent;color:var(--textBody)}#settings-modal-content .settings-select option{color:initial}#toast{visibility:hidden;opacity:0;position:fixed;z-index:1;left:50%;bottom:1rem;min-width:3rem;margin:0 -1.2rem;padding:.7rem 1.2rem;text-align:center;font-weight:700;border-radius:var(--borderRadius-base);border:1px solid var(--codeBorder);background-color:var(--codeBackground);color:var(--textBody);transition:opacity .4s ease-in-out,transform .3s ease-out;cursor:default}#toast.show{visibility:visible;opacity:1;transform:translateY(-.75rem)}@media (prefers-reduced-motion: reduce){#toast{transition:none}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0;user-select:none}@media print{.body-wrapper{display:block}.sidebar,.sidebar-button,.top-search{display:none}.content{padding-left:0;overflow:visible;left:0;width:100%}.summary-row{break-inside:avoid}#toast{display:none}.content-inner{padding:0}.content-inner .section-heading a.hover-link,.content-inner button.icon-action,.content-inner a.icon-action,.content-inner .bottom-actions{display:none}.footer p:first-of-type{display:none}.content-inner section.admonition{border:2px solid var(--gray400)}.content-inner section.admonition>.admonition-title{color:var(--textHeaders);border-bottom:2px solid var(--gray400)}.content-inner pre code.makeup{border-color:var(--gray400);white-space:break-spaces;break-inside:avoid}.content-inner blockquote code.inline,.content-inner code.inline{border-color:var(--gray400)}}@media print{.page-cheatmd .content-inner *{background-color:transparent!important;border-color:var(--gray400)!important}.page-cheatmd .content-inner{max-width:100%;width:100%;padding:0;font-size:.7em}.page-cheatmd .content-inner section:is(.col-2,.col-2-left,.col-3){column-gap:30px}.page-cheatmd .content-inner section.col-2{column-count:2}.page-cheatmd .content-inner section.col-2-left{display:grid}.page-cheatmd .content-inner section.col-3{column-count:3}.page-cheatmd .content-inner h1{margin-top:0;margin-bottom:.5em}.page-cheatmd .content-inner h2.section-heading{font-weight:700;margin-top:1em;column-span:all}.page-cheatmd .content-inner section.h2{break-inside:avoid}.page-cheatmd .content-inner h3{font-weight:700;color:var(--mainDark)}.page-cheatmd .content-inner h3:after{height:2px;background-color:var(--gray400)}.page-cheatmd .content-inner section.h3{min-width:300px;break-inside:avoid}.page-cheatmd .content-inner h4{padding:.5em 0;border:none;font-weight:700;color:#000}.page-cheatmd .content-inner .h2 p{padding-left:0;padding-right:0;border:none!important}.page-cheatmd .content-inner code{line-height:1.5em}.page-cheatmd .content-inner .h2 table{font-variant-numeric:tabular-nums;break-inside:avoid}.page-cheatmd .content-inner .h2 :is(th,td){vertical-align:top;padding-left:0;padding-right:0}.page-cheatmd .content-inner .h2 thead{border-style:solid none;border-width:1px}.page-cheatmd .content-inner .h2 tr{border-bottom:none}.page-cheatmd .content-inner .h2 th{font-weight:700}.page-cheatmd .content-inner .h2 li{padding-left:0;padding-right:0;vertical-align:middle;border-bottom:none}.page-cheatmd .content-inner pre:hover button.copy-button,.page-cheatmd .content-inner div.tooltip{display:none}.page-cheatmd .content-inner footer p:not(.built-using){display:none}}code.makeup .unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.makeup .hll{background-color:#ffc}.makeup .bp{color:#3465a4}.makeup .c,.makeup .c1,.makeup .ch,.makeup .cm,.makeup .cp,.makeup .cpf,.makeup .cs{color:#4d4d4d}.makeup .dl{color:#408200}.makeup .err{color:#a40000;border:#ef2929}.makeup .fm,.makeup .g{color:#4d4d4c}.makeup .gd{color:#a40000}.makeup .ge{color:#4d4d4c;font-style:italic}.makeup .gh{color:navy;font-weight:700}.makeup .gi{color:#00a000}.makeup .go{color:#4d4d4c;font-style:italic}.makeup .gp{color:#4d4d4d}.makeup .gr{color:#ef2929}.makeup .gs{color:#4d4d4c;font-weight:700}.makeup .gt{color:#a40000;font-weight:700}.makeup .gu{color:purple;font-weight:700}.makeup .il{color:#0000cf;font-weight:700}.makeup .k,.makeup .kc,.makeup .kd,.makeup .kn,.makeup .kp,.makeup .kr,.makeup .kt{color:#204a87}.makeup .l{color:#4d4d4c}.makeup .ld{color:#c00}.makeup .m,.makeup .mb,.makeup .mf,.makeup .mh,.makeup .mi,.makeup .mo{color:#2937ab}.makeup .n{color:#4d4d4c}.makeup .na{color:#8a7000}.makeup .nb{color:#204a87}.makeup .nc{color:#0000cf}.makeup .nd{color:#5c35cc;font-weight:700}.makeup .ne{color:#c00;font-weight:700}.makeup .nf{color:#b65800}.makeup .ni{color:#bc5400}.makeup .nl{color:#b65800}.makeup .nn{color:#4d4d4c}.makeup .no{color:#a06600}.makeup .nt{color:#204a87;font-weight:700}.makeup .nv,.makeup .nx{color:#4d4d4c}.makeup .o{color:#bc5400}.makeup .ow{color:#204a87}.makeup .p,.makeup .py{color:#4d4d4c}.makeup .s,.makeup .s1,.makeup .s2,.makeup .sa,.makeup .sb,.makeup .sc{color:#408200}.makeup .sd{color:#8f5902;font-style:italic}.makeup .se{color:#204a87}.makeup .sh{color:#408200}.makeup .si{color:#204a87}.makeup .sr{color:#c00}.makeup .ss{color:#a06600}.makeup .sx{color:#408200}.makeup .vc,.makeup .vg,.makeup .vi,.makeup .vm,.makeup .x{color:#4d4d4c}.dark .makeup{color:#dce1e6}.dark .makeup .hll{background-color:#49483e}.dark .makeup .bp{color:#dce1e6}.dark .makeup .c,.dark .makeup .c1,.dark .makeup .ch,.dark .makeup .cm,.dark .makeup .cp,.dark .makeup .cpf,.dark .makeup .cs{color:#969386}.dark .makeup .dl{color:#e6db74}.dark .makeup .err{color:#960050;background-color:#1e0010}.dark .makeup .fm{color:#a6e22e}.dark .makeup .gd{color:#ff5385}.dark .makeup .ge{font-style:italic}.dark .makeup .gi{color:#a6e22e}.dark .makeup .gp{color:#969386}.dark .makeup .gs{font-weight:700}.dark .makeup .gu{color:#969386}.dark .makeup .gt{color:#ff5385;font-weight:700}.dark .makeup .il{color:#ae81ff}.dark .makeup .k,.dark .makeup .kc,.dark .makeup .kd{color:#66d9ef}.dark .makeup .kn{color:#ff5385}.dark .makeup .kp,.dark .makeup .kr,.dark .makeup .kt{color:#66d9ef}.dark .makeup .l,.dark .makeup .ld,.dark .makeup .m,.dark .makeup .mb,.dark .makeup .mf,.dark .makeup .mh,.dark .makeup .mi,.dark .makeup .mo{color:#ae81ff}.dark .makeup .n{color:#dce1e6}.dark .makeup .na{color:#a6e22e}.dark .makeup .nb{color:#dce1e6}.dark .makeup .nc,.dark .makeup .nd,.dark .makeup .ne,.dark .makeup .nf{color:#a6e22e}.dark .makeup .ni,.dark .makeup .nl,.dark .makeup .nn{color:#dce1e6}.dark .makeup .no{color:#66d9ef}.dark .makeup .nt{color:#ff5385}.dark .makeup .nv{color:#dce1e6}.dark .makeup .nx{color:#a6e22e}.dark .makeup .o,.dark .makeup .ow{color:#ff5385}.dark .makeup .p,.dark .makeup .py{color:#dce1e6}.dark .makeup .s,.dark .makeup .s1,.dark .makeup .s2,.dark .makeup .sa,.dark .makeup .sb,.dark .makeup .sc,.dark .makeup .sd{color:#e6db74}.dark .makeup .se{color:#ae81ff}.dark .makeup .sh,.dark .makeup .si,.dark .makeup .sr,.dark .makeup .ss,.dark .makeup .sx{color:#e6db74}.dark .makeup .vc,.dark .makeup .vg,.dark .makeup .vi,.dark .makeup .vm{color:#dce1e6}.tabset{--borderWidth: 1px;--tabsetPadding: var(--baseLineHeight);margin:var(--baseLineHeight) 0;border:var(--borderWidth) solid var(--tabBorder);padding:0 var(--tabsetPadding);border-radius:var(--borderRadius-lg)}.tabset-tablist{display:flex;overflow:auto;scrollbar-width:thin;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:var(--tabBorderTop)}.tabset-tab{padding:1.1rem var(--tabsetPadding);font-family:var(--sansFontFamily);color:var(--textColor);margin-right:calc(-1 * var(--borderWidth));background-color:transparent;border:0;box-shadow:none;cursor:pointer;border-bottom-width:2px;border-bottom-style:solid;border-bottom-color:transparent;transition:var(--transition-all)}:hover.tabset-tab{border-bottom-color:var(--tabBorderTop);color:var(--textHeaders)}.tabset-tab[aria-selected=true]{border-bottom-color:var(--mainLight);color:var(--textHeaders)}.tabset-tab[aria-selected=true]:focus-visible{background-color:var(--mainLight);border-color:var(--mainLight);color:var(--white)}@media screen and (max-width: 768px){.tabset{--tabsetPadding: calc(var(--baseLineHeight) / 2)}.tabset-panel{padding-top:calc(var(--tabsetPadding) / 2);padding-bottom:calc(var(--tabsetPadding) / 2)}.tabset-panel pre,.tabset-panel blockquote,.tabset-panel section.admonition{margin-left:calc(-1 * var(--tabsetPadding))!important;margin-right:calc(-1 * var(--tabsetPadding))!important}.tabset-panel>pre code{border-left-width:0;border-right-width:0}}@media screen and (max-width: 768px){.tabset-panel>:is(:first-child){&:is(table){margin:.5em 0}}}@media screen and (min-width: 769px){.tabset-panel>:is(:first-child){&:is(blockquote,.admonition){margin-top:1.5em}&:is(p:has(img)){margin-top:1.25em}&:is(table){margin-top:.75em}}.tabset-panel>:is(:last-child){&:is(blockquote,.admonition){margin-bottom:1.5em}&:is(p:not(:has(img)),ul,ol){margin-bottom:1.25em}&:is(table){margin-bottom:.75em}}}body.preview{--sidebarWidth: 0px;overflow:hidden}body.preview .content{height:auto}body.preview .content-inner{padding:0}body.preview .sidebar,body.preview #sidebar-menu,body.preview .hover-link,body.preview .detail-link{display:none}body.preview :is(h1,h2,h3):first-of-type{margin-top:0}body:not(.dark) .content-inner img[src*="#gh-dark-mode-only"],body.dark .content-inner img[src*="#gh-light-mode-only"]{display:none} -/*! Bundled license information: - -modern-normalize/modern-normalize.css: - (*! modern-normalize v3.0.1 | MIT License | https://github.com/sindresorhus/modern-normalize *) -*/ diff --git a/site/dist/lato-latin-400-normal-W7754I4D.woff2 b/site/dist/lato-latin-400-normal-W7754I4D.woff2 deleted file mode 100644 index ff60934dd0ea9cdd93f961d2dfd1e158357f2a77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23580 zcmY)UQ;;xB4=s$2ZQHhO+qP{!W81cE+qP}n_RRl&dsm%ZCpTT)H=V3nE9rE_U0#d{ z01)6m)4>5i_}_X%0|21i`+v{=xBve)>|#$G2QUMG01*f}$QV;Z7^t9Vh`@VY=pZ2g zKsF!};7~UZ0?-f)@L*9GY3zb+R%30Yp<6XjH7CN^jq&v(63p_;aREE<1cgbu^q)U+ z(iFy4_$|M9B0=cz4q^$eVHHHSKq;Bg3U)N}#8~#f@_*qa<-Kx5pD8pJ$T>ZuO3WDn zu4gJWuY$vO`tr*gX1ubl-KLKp)A*wdZN?`In__COj!g^utG3)6_32W-E;zJJq=`g7 za23~7kwIjq{Y-H9!-P7mALvSZ0vPR@i`0(2r{(>?4TTAki0~Wk3W!73_};_q@WVlo2uQdmL86wRJ<3@#KfU=j zoBNu$1!5uN%{y`)ym6oR~@@kx@Vd9rw-TG$Vl# z6@~*Mjjv^>n-&*KZ%!(2-S*n;TGu?(-rRBT|GxXCY;KV6pzkXYBrun6Xa=|s6CkXj6-HkSQo<_U z8#>;2A;yuA9)YwGMA$8UHd#+E)}8ChD$|P+O~^s9iffl>5b%3%L-=P;&e&$TQEr2P z(agRgDP*C9)zo9E+8pbQ=kXUl`&dHQK&{Kvek|xgi($u$m8$t8@7n?sobI08TZq*vU(ZXE;yYE`KGu9UQP8U>ouD1BBYsmQ6P zbJ(33?`B~70SS-@Xy@~>3g8w?McH|#k%ED_uCEaNo{VH6udVg#iq#Jci z&ysHVb_S^$no)k)J-oeYivU;0Rw2j51H(-inay=UU4}{TJ$Rt1u7}3xRr>m_`yZ#F9-`zJC4qf0!Z|>r9!NPExFd1w<^>1wdb}-{6d8f5Vh|Xt#Dh_8e0j)#&Dg zKtVx=f4)MSyPckgdODOPSb9GgEn&2Jo+1O++6eVF?l=vZdboQAA0lz{O)S!QV|ldS zPyv2RcC*w$>(=x>km9uQY~G~Ye-qnbJ4zzAz%WK5Ukb;q~r8_7=l7!uvyKv zgC&(qXVOEElRg&ae49)*B2}+iZ`NDR{IdfW&8e)gKyZ11iIJJ1sj<&T zpd~Rj)i*Yr8Rhl@n+hqYT)_WB#m-I0$0Q`ZNK2lMY++I}F)}kWHHPO50g4%jl$4N? zoN6CXWsI9_I!(sDOThm>7cOXDQA#ZWQktk$6DnH3sL2Q^NokG3+M$B>2WUY}f>Uy4 zS1$jS6j1Z(=n;-+N^+(wr~ATEz^Smm)rMf%FN>HBZ98=7cj2y2<#`=DtH{yUA$|NW~^Yd5zkYdroSv)svYon-m7t9$l*3BR8iFX|!Wy=|#^4 zP{kiXywNFVOx-|ZT47LKj#N1%vvV|zLx5jz;V!q?0&WHV78gmdE9Mi? zYIljLn?(}8BI!jQw1&cZn!S@`P2MnB(R8^GvSDdqET0X{6zPAA@cNL3hJb>M3P;=E z{(s>QOiZfk^$DS0sS9b6uJEx|lqsgI-aq;;4hV!=;O&v$Yb(S%$a{$tUkxcJ#D|C# zSrR~C2@2B@RI%0-H_`4NnhFj_Sn*>TL6Ld&f@Yi3%u4XoxhAv;2>A z(%XsQB&4LYM`UeIXS>3Fl;KxgS#;#0sH&_lD|HZ^%W@#hEcmjRSE;~scDer!oOQ@| zxLi+p^ffLAtI(5Ch32E!Ul>{{a%~kq+hm5v(>+ zQ&nxme*(}dLs+a|QKI{Oxq`jx#l&6j`mbmsW=zH;ebS6gdy%;!NwZ;fYi5&kMsNBg zNf@z2MP=iX$^xQ6yzJZ>=DS%vQ{P1RHQI>J)hI7MWIrOi3!1k2@c-bLZ`x=ienlueGIBquAUXk8W$r~sTJ-EkPGIKOFOK@p-Y zyA3Mwz+>_2WnM3-m@Y}?Qak5;Uy$AJ^PEP z{L$h}%J*KD-p2}i!N~usu?hbKLMZ#>;N)t*>m_+}&CaRDMx`dK)#^F+%(jgh+S9F^ zE!hp@uD+<*=PYlg4_o`gkKq4w#@gBaJIW6E->WaWnRw*n|8j7z+&@3QKAZyS|7uJN zXreei)ls>vWT)e8USFxbwn=vKVWlp3iq%RclP5jf7i9Q>4p>a9Iv=1>G(~@@=wcL} z{SPsfoLQDs#@(`2%oi(VX$(Sny8gf1Xix7ukuy4X=;eULA5*7n{0U3|l$=V4gAlwK zVGvsDESUG2HOWx*;fBYZ@k;c_9ZA7UB`jjk9rUk90D>?W+sjA*00Bf00KoZ>SMY5U z7jb%i?ci9K0#lrlZf0g^>g>HO)c<2K)+_vIM1aY2me4V3^F5PTWe--)Q>PDdP5Iqy z1;;+En1gb>T7z0N8>xZW0%?c=X6QE?l>(C2Kss4W7)BltoD`Dwn~=~0rS(Juz@e!2-~0CCTL ziv2d^9Qt+O91yx5Y1**@>>QrGTKJjtTVzhlpxo$}5qZIEemW%*q*}>mB(TW%r6J3T zpj_Ygl5>k$g|yAo|v10J46yx?2{dg0`tpBBv43plp+VN_{|w4Tpe zMR%twjqN$L3d(7pPw>8Hcq+D5`E$r^(!L-n*s4pFo`;F27xoYeZ2(E=|{o{j_eA0OgRq#;i zLe@oI0}w^VukHn*Z5s7_5@01AZb$%yKgI9DW9Xh{9k*_%)!Kz6g*0Pky-Z2XMe9_@ z7u<4mUmLN6BLjb!-ABzpwFmSO!vY5qrdTKm?d-T-B5BulHTO{C)Tab^k{ly7s+)rY zf~MXe1IRG*F2@W>@}rvWljv@S{Bk9wfR7^yCDsLl>DE;TpDQn#5vMbz1U4y6Q2_JK z(lHY>{$*tz)^Anndst7(s`RFiV+>iQ8xJDwgR(=}e~c2t|~ zjz*BVQ-fEsCQ9RSIxTENQne4Y#7HOP zE`f1YwUCLnZbMG3i60PBCZ*1|t? zSea(N#Ejhzh=)lWZbE!WAR!8e4Me$g1oXW7-kfl=QU0?2tz2Ap+z~|@6;7&#*($RC z1kCk$F@^aw;cDMhRV#gru=9{l1Ftt?7MqGb7s7cgUqSYnR&@EHKA5hvzuh{3~DD?;WagRT&d7|_fF`%$^*ydIKQ#NdWc9Yin>LzjIn25o+V2ZMs(_~ z>3pzcu$QYiwZ0T@L6O)}mOK$jg2hY}_tKUPxe%O0Ub0`hmxBW6Pg()qZ?_OB^RNSbc%q^0u!A`qv&%7po=vYwU-I!0+8ecJq z*v*w?nXSPb&q^Y!3ld=v8Rbz=GE!QYaQM4@R#$Q{QocBSIGtH(Q4T|IH72wdB~s*6 zxRURg>&*s>Ju3tN4dT zW2>AlF>@qkaX0l*SA6^=R;zH>n zn3F5}@i^$sqB%QTdwhBrCXGCp9N?>3W@FHFdz~pU{y8(&jq+y>tNTRIFX-9W+fnMS@PG$0SzgGIw3)mg;BW+=ECXDvQfB!(JXMNON`qr)^1+@H{mUpA5MU= z9)S?xq=D}1*e#%jeB$~=co+n1vxA#Js`Yhh;Z?v~e2Q-PvmhdIws&M+vH8gqTN#v@ zsyeYl){vM-sIa&15QD4?zZ9)#gJfPdlvg8PfAViYV~)bhLH#Oclzy^AOz36vVqz{O zU7}3>1>NtoT+58x;LSUSS}lJ~PiSe|k9Mlwr=UwoL*nsCHv;xD&?4uob4~+spo;fE zczHJ{e%3aGt2oAt#i~udS^o#vN@miKuw#w*&H|rZ@8e1MaMxnVgt?WjiTw3gxPFNP zX@w~^1j5r-H_<*XpZ@yx!k85PU##}xGMDP+Ju9Mzay|J$(eJjm)HR3`h}b zRObVHrb59^Oo=z1B3J*yu*@G_s^2jV##7LMRT_60_Z#f+x)1jSKI1jlT$X(7hR$3= zUJp0ecD4}u4mrTubAo=f|7?>yKUtufCZ=B9{&O~(xw@4!vW5^LGV^hQ0$xD}$K_-h z1WNHc1@R+AwDN$lThtOZMB^{pec*gl zK)-vT>W)?~w$JT+yWn4arAe=>cPCr8X^(x448jU>ojI6AwRV!~)B*%~U(93=tGGw7 zraC$d**G z8mw#{Wt>#Gi_agYDd=}YzF`uj9TYIDZdyq+O+6@R(n zFH-G?TP;Bja1PWnbQ~j>%V`qWF{L)0^vJx31KhZlFNFl;y%077aJG>)ezn}F`r@O43ge8cN_naa z&3Wm~Zq%~DuVNPTca#isjhmW>oVHmcW@h$63t>>2w+BIB->8Je+q;A-&0|6RILS zUA+VLG9H_yAonTUTrf1dQruRSuSj(AxcQMY$H(Fn^rCbb!zfwv%BJP06}rwGHdiOn zlRg94fu8xnpa#GAbX67%L0ir?Xg^IUr`k&^#J;gjpj8v60-Z{XJvd$Eo{RLfK0}E$|oqik_WMQ|>`4`oY5JwQ`!mjiZy z5mi@gm!&jyw+L?bJba#Sj=GYjNcg0@3A2tsJG3I0Q$6HmE@brxQext%nOU-iIs{_Y&bAAKzr~Vq zOe5a2*&w4Iy;LmQw(AZgTDLk12b>55$v#okpr7g#js@#=g<5aI?Knw}CgTNY(d0}7 z2QvNM-U65qQF#(x)k4`&b+=<-A{Q?3JB-8KDr;5>{gMa$Riu!>iG-1Mq_lZX|^|q-HT2N(p4tS9IKK- z<#7^NfYS%4Suv~X2-Lzw!P?sba0N12lG+|q$WPk+QCEx(0@IP|eG8L|6tVy=u}=RMpjm(Qj}UvGPS=XO$6- zcuMlF(u9n7VO!}^6^r%NzCXDWWnyQ<)7EochIMp8-N^VC2SWQbfC}dPQ2-;=3H@Px z7U$-2C?38Wd-%fUb(|DI5*W0oc~Y6MHlfQpO9f6!IB{UYk!awD9MKI)K;U!lk1cTw z>*dW%VMa7=&HRwg@1%$=4(0iKVeTwlY!~O<2J<>FW|@M_eT2+i_bAREVf02}Q&iWK z<$Uv|vg+)f%fRRoX*``PCVA4uH{mXcfajo2ZnsP8-WwlxQPvnc#Qw=y=Xkr)=2zIr zw~@%#zEazfIdvdDHJy~3kBUZ_*6#ob*x0|bUMfomC7iMsVQ*WLo zqqx?Wbcfs-7BxUj8SzitY|&C;#++*V8fbe(d`XG755m4gmDMf>*mcs>63Qt|N?8!x zondELYPo*vOQoTDrL!+VGlXgPn#o3s##(I=ErmFaR+c72A%{oGB4myy-4{_2=}#{? z9^o2QBF2!aZ94zrT@f9R0ZhY6f1p!%3YHx2URtddcVhKhm4hrNykh1o#Ie;H3fGb+Z03U%!sGG&Yrd+q9(m|%%xe@r25)n|$%lVu@c7M1+np zEXVOA?yj5n*2dQ+E9PFHw(G8TWv(07FG?*fy^HC??H)EK51{8@%^DvF6y)^q4ZXNO z;3#dGv;=)wkT3y&UMJokOpb(>wj%$yB%k@reROx`vO+q4DaY(J-S$lHTaIke14eQ^_c&w`?eMGDhPj8LorRT^B`hU7CNgH`*<4wouwt|?VRp;8shh_oG3I5o;#@hM zx+w$sSjpBYE*sONREqgX3tR{c-tGJ&$+iR>=^1qiB`S9bIt}8x1L6M12?6w5oFXm3 z3IZKsQo5swiF1PWz9@T?Fc5UY?VXP&^wAaXd6s+wdKs@)Q@UhcL7zqLq(Rj>h#x%BZR zdtsTV44Ni#|#+v#&1?`jC$ zklJ-^GRa#CcG=;R%hn;V3{ge%ZL2}od{W~t&g>o?w9=BUavGy9!I}ZOJ#lcwZtTkg- z*n^)}TcS%59d;tK7n6OL!ZAC&R?i>ZwL^Q;m4eXHmCCod0JLOl?A@WiSodktlJHZ3 zWTIW59G*Hc!l87!Wh03jOeV;>%3bReY*-l+r4dw8ggSW$c%#@bgizz;UHdq$qgM-2 zT3(;HddJ;dgsZo^Vs~>Gshm<6se{i8q|{|V>aX-AStww4vMJCbv9JRDmqEfMM<*h4 z^{sqgYsVj0Q}0*E!@lFsWT%f=mvzJ3WlL7>5{ly74&jkQX2uaM_df*f$E~=SgET3l zz6E?NjEy|M5T$Ha4wtI(A|i92=ZeC^V&&6X#DO%dKk+4!5_VO8Mo|bXWu|CFTpBuA zQ)#8>bz8*WRyR`@7t?cZ1neNc%yuB3WzeoUwZIauf$4}2;r~ih)~xigr>#&Q7ny)~ z8ny+@z1ngs?oP%tY>ns{k`-mpRKufHb3A4?vi-(pCvE4PoH8u_*SN6$P zn1>&|gfjM@zOTy^|7p<^S6l{W(%1;7`qOL0Sf`7JlxG2bzj1@$)YAfB#j5mSuj}B| z&CcLe4ly}sh)Pk}WS)GY$8Y@Z?@#l>$+gGWH)T6+j=wzTXsmjYoiL zg{syZG*>9+n$>xHLk*BaJQZ0 zHv8n4zE|D-YX5rnc|`Zh?Lqz$!H$JAtsJfN*ebo6Gv$YZw~b;DiO98RIK_-t(-#ZU9+pu)EnbPM;UO1@NlcS85}_K|f?J zU!#FIIa+VaG|GP!HKT{{bxxI^ncZIU3zd|<&l9bKt;z1|o8Z@B`C(Nsklt`!e=h(w z`27ZZ)t>h8T6NiJga?2(07r+6zto_|FmJZvWMG$p-BL9ul3b=>xUCR1u;PHYCVS})-)maH(k-WSz-0-uOEnSLXQP3Wx_K?c= zec2dLGbshI; zCB{FSc&a0&D`{Rr&Bb)6?rhcIQ)c0oh~{7xTOHm~)@nYnDjACvDCAHYQf^Dp7IhGw zS=HI32;4P3I^XVIq+(hna;L_LZER*jU@u)=}!2HI$T7G*~j( zP1;sF!Cza^@w7T&(yz~f#4CtLr&@X=YY0$&9bf37yfY<_b-C{F(sbB zK%E+JdVVmE`4a6*f8#jIgK)>ZlnCK@W~LWHcloJF7QBznp{pA~-xA7R-s!I-eMh`9Wh@ zhaeF}@@hq85<)0+*A6Vk6&@4=a?zBA05`z7y4+~26I{nV16B8`*+oS^RJF(vnvKDzzjk7+ns9n?KrAP5=I9@Wb)W`Beso&kRwjY?TqKaXTr>0 zUbEf~8pmE62eHh&HR^Dqb~80Yf_yC3E|S!*M2V{C1GqRpXFYrtktK_U)@}>VnqPeS zx_TSJ>_PfCv`a?e3(a*yK|4p3BrP}QXg9Sa)yjH(-cs>V!r zhP};fX2z?Y%ZkGt&XG&P&R$xxf}0drS!w7-ZY2uEvFr0eBkf2D(IQS!U~s=r<-o!m zX7WTDR7$TXN4{`OFIq>5T;rI1CMU(}{WgH}1c^#%vp`5&z)@5@!?sta-U|k0`88L3 zwA8k?m>O`G;8Kv&rFTw4w)qa5C~jx+^fq33*~?Xv7KD;%#xa*MdEZ||@AO4=*(tHM zkF(7|g_Npu)ZRLQ=YCmKy#N);JSA&|SLEaDuPMCw_!q4@t}(MUu5dOcy_r(Qt4k+1 zWt!BT1JdsGZ4AL!O4t_SNV$ODvxl~rIMrwKC(0JF5dy%2e&TR%un6=ibUxONyZ1G11rh8Axv@L43g7Z$8zRTQZ|kr+dGqDj#1RER9{b9zR`< zmv?xT<)b4vmjSR)7g`ZPSG>09+H}UN9q7aKpUdjNQ>Q!~HswN+v%$jR7)2^vLyoE| z4Ru+;9z1%n9QZ|&oW;tumE-xT^}00M^3bO{MWLfv6BJlEJI?dQrW1_1hA=*TW$C;q z+E_39G#Z!F30ODWb(1z4T|RYkIs0*7&4RaJZr)`{j$a)A!f54 zb6C}GZEYa_Qr+fsKYPxc3BxCV`?x-kr8Ru6pcctT)Gky!ucXPW2@00o=SNRXE%pab z7?bHt8Jns|S^go{BI*y{Nsu;4r-RZL|*4EWvFJDghMIQz2<*YSPlEJN%j-mK1EGd$csy;_T}B`B~PNoK!XLc3faw|M{NWsckN$ zV)sjZ&(1AgpVox$H)2pLuB9#5*6|*kVJmSY-)-^9+^1X zsu{N9M*TKtx#`)&Puy!IM_RJ1f$4fD2<&ugo-cT%&>#x~p-QwYsz-Xm&g}nw+XcE( zL6eR4rgqA6gywu2&;!zH!ms>3nTUbXY!uzwM!+$8x0)rB8XUis1Pz3`8Ta=iq}MF; zK~Kq%4ZhvHi^!b4zl}OPy}Jqbfj)g`xetj0i~S^mB8Hpy?}ADYhYdF1Ed}q3Spp4P-K~jfjnCqObNUblJjvnFU|J-oBox z$M@k^GlWS9v)woGkEmi94rM@$tJ7sCWl|$DPb|tzaHDWFbE>dnr?JW?qNxFohsy`a zS*2j+I>QM?7EKgE*AwppDKM#-qNvo^%s>T|WC9VZQgNz}W42|OqI6|0!h5p>kCBCa z<;)631Rn{gXXrz@Z#x>Xz`hp2f>Qee1`NX6P82k@{KCD@Z+(}*h#%x)|Ggc=`$W|% zxUNyT*Ev-w=@repIZ{8hGE-eDy<$X9_qeunU3iQfMcVG zK&Vs4qaG?ru(X-V4F;`urpr|N);5@A^w0zX;Atd$= zvuWSvif42cBqJ}~zW!{rHP)C>xl(Cf4h)&N zQL3gg)}*15c%^cj3XHe$F}lbh+1r#E^=wSlNs$8wyyW@lP-9Hlv42zLioc8JdbnZp zVfUeNp%JzR+Y0e0+bTMb_H2J7l2`>#^}&~AnIq- zMQRkad3)5T_SjWfd=%B}-o|+(aKFmcuAH2kxpD;WsLx+6E?9Vpapz5yjhQ3ol7>Zm zrq?tH0^h#8-r3W2XgZFrG30vA>LZs| zXU#6xBC_jG#Hg*WMuo|-i+85JcvPWl<=uHvY(@m(P;F$EO+}OAlN=^hu=p3*hJ-MY zyc@|NsW&OmlrNtn?Yc$SIpuwAUA*%!c%UyDU}YnWCyHD&JiK+Vc){pP%fgM$BmS{b z0?4(Lf)_JMHyCl&NM=!C!yVGWDMu)R_Zm?XszRw$DEkn zyckE*ETmV5jGoT`qe-%N1{O%ZW8@R6OSF<7bYv6MseRbs%d2(70WjZ## zLZpc{i&iUdNFIzeQ+DHCgk0jnrkLWj;7*6*A9CikT6hFTzgG4v@ut4$={=QLd%lNw z%z2l7J-d{C<&L0>4lU_-p0wN*?75fjmg8+vvt{7anMHdRH6^JtcdDB(EnF@<;(UuI zFbt$gI&oQjh!Y%3ps;dcu%=NNRTwc9?SH^8(yxPXb?~-RCY{?f2CZI!k6g=OC5VD%DRq z8-2Vr<|zOQgf3je<+(oSd3eJXkeaS)I7aaQY3$qG`_SdyExpI%9gW@rym*PaL)>Bjvz~Z!b9iehZ2KtADUmZ;{k?$H-yRo&7Cq^I%z=&p z!uS8Vx&-_y;;~l(K;Osq@lF3SWKjdl-Lky8zV)okoHN3#OR1^hp}xgb-MP2IpS^n( z@d(nz^|B$ZU6{P?nJC;W?LiF6>z-L$L{k5yoN)gY_T{fZi~;RP@xa~T>&&(J=Rot;zpt-GPd`F6 zjtxztZ9(=y=3YAxd&_Ai?$~H_R{t9CveQs&3)j)At83>6^Pc8?v;`>9f_;k4|5kOQ zaGs-vLGlKN0u{8kAZTFgzTY$tQwIY@-PII%=2?aVMyp;qXvA0O=Y}2jy!Y-l2%8Fa z4}GJzbmUuEMLQ-{8~GgBDcAAV-Qi2JLfS`&A{u2tz)&C)ydD=?EGT>11Q=gBmw&3& zV!f=z0?*vgaBK@zJB>OGY01rPpo})rjJ`*uBIrFjtB7CC#!<`p{))3u1|5GW9uu5A z{g|t(Jg)O-evzGdZY^Oi5T;?#IE^uneJyXp6$HZnYxGkc+SoNd_pWs!_A|7`CF)9O zYzr%cQ4eN9_qDX9XwbhiZ<4{d&sfjzqg%5qXSE0EV-l1t#7CBwNG!#lP^9Mdwjd%$ zh~GqfAB0JA{}KCA#`63=#b}fxZ(1c%WaUU47mEb+TAp}r@DZ~-Vv`WXwc zY7Pw|ahE=HdEclg3AK;SmK*|xw|ArE;rFsqVK2kF)1SiDN8>eXpgHQs>1Hzglm=FI=WrRr|jdK3P1e_Z;qj9}wyVlt6Sa`(4*U<0x*T zEXA$!!VvhX8&Pn==LCIj(di}g2l0>V}s(B{QX!F8h(c(}Z!PCN0HB%43 zM(8Aa@+6`51C*v~K^qlX38amcN0JoUmdz+M=12fzJ9n7lnH|NV#MHac9b!g$geZN~ z#5wQ_(@2T0&~l%!^8Y+>g>Qx^Zq=qVbx#t(kIvVjt^SD-naWs|B`F*^g@ek!8!>uw z1N8SZ$RGW2lVzfw4^^j=NFe}{VS=p02J43KW+}rIX#65_&g23BO^hZ zX54dj4b>uOREp?P*|z=g0tUAY`UJ(^Onq|;raW+SufQ<%GdWJ?!A@d1w6F!6;$ zXnDXqJA0LyA?XG90#WM=Nv^KT7R^AklTVC0>Byxf_`m>j(Kl&iK6sp0g|X|*2m~1& zYTX>;3Sk*1ub%nHy==PKHQALFQI6Q??>{@#dfFflee~(}d#T6&{GgF9@&5~%yB2+0 zGdaaysUBBndSceq%u%P|nXV(TyNCzyH9@G#%^Kp=9x~rzm-u=0YSaPLtsr!NzU%xcv9%pgqOCtpgxthFDA=VVk7HXGDW!{b6suZMwnD1gbP zm>V9@c^)OE1Io)GBH&)E`i2jR6o3pNnLyO$@fh_%6O(Wi8l(=yFQKc_^DiznO`!K21dA6Euc(<gLjV5eANWES@3BMu-(}`ppJH;J z_;>V(I+&es`pi<-%oXjLUG2#DP^FdISxFytQ=1!`TTA>ub{^%tXUo_L%(R;57axw3 zpVTW5mVd|e`%(U+VmE)w1^A4rSQVoo=X59-s_22gg(C|=2(KRRuvHbiWO{M!7o$Te z#OtXquzMDfQx=zeI2qHx_<2hGJ@}bgs#b|24#y$Pd?Qz)@NulP4KOMIN3Lq9HJ(qI z?{Gz-LL2_HZLw9>z=+(aWJLP{bxZ<^c#o1Q{M2zS?&Im@Z4RW95h3kQ)%&7-n&@N(UG|@fBo=$uC^J{2Qfwe3epH08ZQ)60=qER>87Y+j!TSE zw#FJf<4GSTQZIy-MZ!tDVSVi2 z1w7>2mFYkQF~f>bVR*w)a?zoS=5(5G=!C?FT!8E=GXl+>i=Pjd!=>RlvU znuQQ{7!dnV1{(Q7w0s;ub~U}xN%QXj!RE)y!5&XZ>oicO33y5H;F)TZ*jLYAXHA#k zT2yM2HzktqD=V#gE2|_4*^IzI_CPQ|JJ8Y}F`tf61{4@jgflq}*;5mc?4ZUwKOMDe03ub07uM@B7?9E5)QU4O@Ab5 zQt>=?Dmsz$hH03c<}yrnyS!u*CNGX*5#vGMKpOi`$N(Z8f0k=|cmM`>}Uo^`Em?5sXDSnaE z?sGd$<6s_hpkRxuZkR$tVss2-cE~bP1um`2i`>TEZ+vYuptjQO}{w_#Uw=_B3ULo zMwlt;j`r}Qo1kuh0npH$`w4@**7Y-FB+c5^fDtXA15`jQhtX7m&oz@0qG|Vin+li% zeL@1;A{Xdq{(eiy!3%%t;#5aB=ILG4B*;OEFy-gM8=UL|0kfx!1;#W|EJ`^zc*CPb ze)dMcIeg^4N~>+(D}YgzB09cRywEq$XczOJJ@5I{)ssdFz|PMh;DhD&-T67fS5PC` z$THxXpw9;?Zo<{H?=oKK8)&RN-hx1Ie!!vC!NjR@w&bwS=2<-~et zlO7cyW5?-CFbR)u1yw)ox;bH8{xq6SL6@^OJzG(db-%Mobe_;rSv*4?Q&VO5zox3@!b&}qtoOyA`J1MF@#NNU=A zm~gW`?AKQ}SG#snq%ldi8y%_J9;GdG|7B|R#1%7hl=t$ctc&hF!0zM4VuA^jA2|Se zGbDE4jmaToW~yWV?FS?l>BP#I^+lPJ>bRhM&}0?lAjZiHN(2|LW~6vwy_+Nku0Or>2-C*yuVU0Tkce9$S7lDUwJEIYcv9 z|NOU7X2Xpg8{DB}fL?=4KLJzJNEuNRRA5$)Uy3jgUETsv?Mh&vXgkM|_5t*tLzWo! z?yYVSl4s((3X{i108FdcGnlCEbqZlVuqGWnHFW>2D%Bz*h2>)_cgZLV)tN37u&@aj z`q&B#xd=elJ#74Nd}8E(50}y313B+d?*7p2=DQ-J>Au4h-Ar|8&WuoX#zK`bc%?4$ z+B?X!E(&czt4ycv+vuRw@IaRNmv}U9L_O%ok@uGd0IoQHDDq5&lBYRjfz|awfX$mS z>^y?yE*Dx^J73)30I>!-o}2L0Yf&j}WJut!8Y3?Tx{YLr$~FklFvBUoE}schYY-h8 z;@t~85afnkDI@7zS@YeyV_)z5@Hg2#?VnZ)do;YgE%)7dtIx%n>Z6{;E61r1EAWdlIC18NJT`+R6cMr#v;R<*G#&KFMoI%URRE%D- zt38h&Hv!tFjlzyaMMTC56`dt%wg2QpP6s}oI)@PHYIR=~+~N6#+f=grgT(i`mBEyd z<_ zjB)}0#~&{YX>Y1&gVfP?z)=~}^->W8Bzwmwz99-zu_sDEOiVUHHW*-RZm7&~K6@UH z93L%p!#k_CewcLpd4t()(iO8KsE&@A(hiU)4GL^bHWFSVVu2~@ryO;iuJ~LUX{#cU z9fXN)jC30wlcs`Gq~#cMa}ShMT{5;}V)uFcz0o<5-Bi#N-80>fS4V7act#w1PHJ+O zPIIn?YZQdiIs{Q04A!jTI)4?MVXrw#g z@A2vTu9@1&qto#&*R-vol^c~@JeRyPU@Vz0qo&V_0sIP*APq75bdGd{kRy25P{|<5 zr4$~qjr4O3T%`{RBM}s^c0}07T9>jt%dQLk3*@E&?jeV!udeep23ix)Kbx&7ZR(GC zbqs?gNBV1qiwv;SeIS;dMJdhR*a(;swaq1@@U~H%GO;6r&I$_Cv`_)ec9GUOxdVG~=036KpkG%PH1GJz;RrIYx)(Fec`J$@>k< zI9ZmMP$f00<8YXBfAChZCv}PuC-4!v08tqxhEkEDtAOYPg6K71_7;Us9c3E*TVY_^ zVf!5KV$+kJ$&+^H+72PCvedF9ScV(pKvP5aRo%i zx6JqF_@0>P)RB`{rt5Xs=sk_K)GUf**)9fM)3`XO=4>buLcD(O;r=iH)Sm-+7>A`{ z)30&NtmPgMw#AKwgwqx*Aess#jt`XzRdEB3fNjRy$wF1yoRkb<8N2pdTeq~mz$&i8 zQ+fl*57L+wN##gns|5)EM1W;D%H_KxlGgmUnJZXzIYxm$(Xf$UBqPLY-yOCNx z;S^_AkT>sog9D$OUXu=9>sN!*>87-knO}{XAs9F7F4)K zC9N2fMrt+kj!s`0cGn>0kfLpFM37(b-Kevq(xM*x(jodmHZfN3P>PP0F#-5q+z*4= zUf+q~G@m&)Q?tsN2V!+5Nx&n~-bBKc6ep4TBSB}N6!vFE0z5keki2hy{60}3H{5OJ zuFb}rm`A=13ziSK|HLB~a={SUeZ{@7C#*6ayEK72 zS270qG>fE}IGM*ZUI7m3!3W<9D0F++7Jxd}rT&}GS}n6TiHC7o^$git)mrBv(Vg1F4T_k`hDg~41sX3q z=+;aU3;YMl0^KjjldwB!c?h8*vGIo>!_XM}ip*(1cHAm!&Uy-LjONd;Bc1TxcVS$7 ztYV#a7&MipT`#12X042jM0!)VaTh2X?joD%zoNYTe=0<9wZI>4FE2Q)-T{YRI{86; zH{EimItx^H0$yo}M067Ik%)LjC9 z86`GIkenDSV4|(5)Ho*>=+9+Do-cMA7bE?T8+xAngZC!N@shiN(gSnA;p0AfAZ?cO zX*EI^Xg~Rm|M%4}VMa*96?Zpe^!VmVB~0#=Jm$<{)f!T!lPfo|$?oMR? zC=Ci;HjLYi44fBZXPcNDB$~TLG~KL0f?u*|Py`(lyAP4;f9CffAu*AZ7sR=Y_Jg4DZ&hC--HIFH(jVPG|Ii>cL zYGLhPjq(b&&+bHYuKsST9=-3hKp6t#lO~IXVB*GqCDa8QWmKeE&n;p1H6IE}!S~MNmPoywt0R3eKoF+bVhi6|Loja4 zy%v^3ww73Ks{;xH``3a$jphqaP+Vn3L1t_XDXs7lZPgabhP!n7DiF9 zcg4BffPRo0m$l?b{0vZPQ$RYMZVE_0!k%7L!C6(FJMobnU4)`-JK@a|CD^jjl>1&Bz=`Xt0%5GG<$5Y;4-i{p^IX)rX ztHrK-v%mr7VD|0Z0WK@4z-n$5^C-VgyLLdzO{e3~_lW(w8?W1kyC#aH@I9gN9v-9r&I~pRVuHz4qHm}LVv-f7S1Wz zraABLZzE%UAaQ1SsUUyfPPhRygO$v_&nu+PrmH^2oMnk_Yc6I*S8lux+h7J=qkjugk8t!1_j#j0Zyp^M2HGwvSJa>Pv(x+!TDZ=J70n1YTS3Ft^weLl8)*MDH^##- zA)UM;yD<+hu~G)XM?a0Or)q*m4X=DFAZ@92?A;!eMN8jtW3TGwdbedsrZr-2F(e(` z$++RQAZbX=m5qvs94Kh$Drl_ZPR#8!#e-#q{cW;pJg_Wp48QGscLAstct+mE`$454 zJjDgCD+w$yYZ3TfuU-(daFe9#M*A}cG&F>m4%xXH)Y~|HSuZC=tj6ODv_JB8if-3m z&AZBo*bgK58Np|lpfZ zG;rraC|WO)C2pVq8M!&N*dTKa@|Wl~B88|A-O{tRsiB72buM5W&i53_X*{(*R1%*{ z_5H~Y|FF~J`Ek3RPR2K{oR5co*R^H7H0age;eCGdh11tsUtVdxTicAT9%Xso9NJN{ zd~ObGlXWkg2o`fD1=n89SUd}8h{i>azh#PT!oMFH zFnwo6P|D0u@Aex-{h^co?bE+-gv1otsQw&%ykIlXX*T)Li>}&lIHjb2dH@4*tbnwo zNyuI=L0L3h;@>hBA(Qm@%tw)Qg6{IB4B|g%`tXIZ^Yfk2=}GH}yqz^BKj3up+TLmZ zTeuxl83v{Ges`)MSX1{VqBTUZDQM*;^5``^Xi6q&B6s1 z25w#DxtiO}cs2WRSae*nt1t%a z6+poF&Evogm?j7u?j0^#vWKj|4^hHHs%*?JELtTF7fg}U*G&L6A29(K*6Sx)zUSx% zlwW6@wY%yulD4WXX|AbKIuI0Oj~3xT7?Nsn;522Wb=BfOak|dtFUK2hB1-4Obn<e5#~cCT*9>>*F~x~ zrfByYq!%dqLX^G=E#>Zh{^}Fk`hI7>wbbda-GHefo||T0tkV3XegXk!T|_<4FN7gh z1%EKX>yk%`9Q>mMNY87>yHAEjU(yma;3`W|SgmGX++uDn%|D*m<6AecUcR*7tSqUQ z>Xi@0;htEb_Ws@l%xc zD4dBKJHY^5gXdtL-5ZH3{sUX6JN&^h2^%DnHFn*~(ChN|GcT^-FVg{;>L)Wdm+WS3 zGp&m(O-P6@f8H*);wV@=EnB1;rqXn66v2=dyDU@RMkr^z#c2{4~8tAfOk z2GSsuSv4G44TTzw!0(s?OnIQ$$)M7z*U;D;UBR^6;LVtAQ1Bb8iRTe9zR_l*bX*hL zTJ{u+ISG}XE>tkDnvDBI>j1C#iR(DMwO9L<2hDBht+?)!s@!blJT*vOQ@hd=Z!b?H z#n%n=>8cx|saCy$Z_8>)Ph*Y795sh4m5#y}l9_M+=Uf#Zgr5;88vp>OeAwaSA_CXX zI%vKF;KfJM=Z%M-{7>H{`p(Ao`ZNP{0RaGTfb_~wp$i$3`QVcJbol2OFvGj#763Wp zM=NccW$gcaB}N=w>YYPVuWXCfl4u1rlQPR>)Gu>ah<_E6-@Q6 zW(?40f06Tb{vL4bF8ZBF(E_9C9ZsPNH zoIe^NyPzph6GM)tM$RY$^4*0)+>OusTqof?q0SI67_n`i(b{!JysVCK*5ZcpjWd#Y z*c|_E&(LO?6`J3YA@Qx@RJ)Jop}mtR=MZK0{dDUbxK*Z5;sE4XK#DX12vp2C0oI*j z1RMYvhTy>oT>!3M`*(_ij2nPJ&dKnIc8LImT__@ijE{sP+sHo+3^VCl<2bXJPLytf z;d>_Kxw(lM6&c%P=rj!HFGPsc=~!koGM`MIllo4~wwqu-A8QQ8in+HXTP}L|zf2QN zGWQrJB34G7oli7uI@UOu##qK}$C_+{bV_3sW>jywqm!yqhL9FUrth|&!PgAKWyY|S z&iRQXf$JZLHA_~kVzQP#d6LuhkVAD^${0##%tr|nA}?HLl5Oq`rlC6$ zU-JY{zoR(GG`G!56f}f28*h%5t}$fJxUw^UrY|^h;w7(m%^TkGj`w`v%!QA9#m^c{ zCckCphjs81pZTfjWT-SXpRCib`3t?{hK7!TiG_`Wi-%7@NJLE1s4_>fj;N@mH?GXd zULT59E?w<)>T=OW&+R|YumO{1?QG0%I*j?#vLWMoExGH1Df_JW%SST~`o>od$)h*I z;5$ZN`_{F1{)K!upa1u+JFLKa>)dwBPfT8UqmNmkA|;BI+Rma}nF>}_DpjlTQmuM* z8Z>Ei#J@&g~&V|-_XWnJEI5Ao(}@!YCx*erp>{54o#?V%@vakbH%}Wry=%WybMD}T?#;iyD_dtf4$rkeL!4} QOFh<%JiLFgmWQ+r07g396aWAK diff --git a/site/dist/lato-latin-700-normal-2XVSBPG4.woff2 b/site/dist/lato-latin-700-normal-2XVSBPG4.woff2 deleted file mode 100644 index 11de83feaf0fb872c91fce89534fd4e2d8bbda28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23040 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 diff --git a/site/dist/lato-latin-ext-400-normal-N27NCBWW.woff2 b/site/dist/lato-latin-ext-400-normal-N27NCBWW.woff2 deleted file mode 100644 index edb9fa6f492362a9ab1f1d674b8f6e6f4e2085d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5472 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 WhF)K4IGNT+hd8;|K8&%*Sz!P*WW1>W diff --git a/site/dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 b/site/dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 deleted file mode 100644 index 2c8aaa866eee8bee09ee05a9809c2fda7cd87bd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5368 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 al http://Host:PortPrefix/DbName If ssl is set https is used. See server_connections for options. Params is a list of optionnal query argument you want to pass to the db. Useful for bigcouch for example. Options::optionList(), Params::list()) -> {ok, db()|{error, Error}}","ref":"couchbeam.html#create_db/4"},{"type":"type","title":"couchbeam.db/0","doc":"","ref":"couchbeam.html#t:db/0"},{"type":"function","title":"couchbeam.db_exists/2","doc":"test if db with dbname exists on the CouchDB node","ref":"couchbeam.html#db_exists/2"},{"type":"function","title":"couchbeam.db_info/1","doc":"get database info","ref":"couchbeam.html#db_info/1"},{"type":"function","title":"couchbeam.delete_attachment/3","doc":"Equivalent to delete_attachment(Db, Doc, Name, []) . delete a document attachment","ref":"couchbeam.html#delete_attachment/3"},{"type":"function","title":"couchbeam.delete_attachment/4","doc":"delete a document attachment","ref":"couchbeam.html#delete_attachment/4"},{"type":"function","title":"couchbeam.delete_db/1","doc":"Equivalent to delete_db(Server, DbName) . delete database","ref":"couchbeam.html#delete_db/1"},{"type":"function","title":"couchbeam.delete_db/2","doc":"delete database","ref":"couchbeam.html#delete_db/2"},{"type":"function","title":"couchbeam.delete_doc/2","doc":"Equivalent to delete_doc(Db, Doc, []) . delete a document","ref":"couchbeam.html#delete_doc/2"},{"type":"function","title":"couchbeam.delete_doc/3","doc":"delete a document if you want to make sure the doc it emptied on delete, use the option {empty_on_delete, true} or pass a doc with just _id and _rev members.","ref":"couchbeam.html#delete_doc/3"},{"type":"function","title":"couchbeam.delete_docs/2","doc":"Equivalent to delete_docs(Db, Docs, []) . delete a list of documents","ref":"couchbeam.html#delete_docs/2"},{"type":"function","title":"couchbeam.delete_docs/3","doc":"delete a list of documents if you want to make sure the doc it emptied on delete, use the option {empty_on_delete, true} or pass a doc with just _id and _rev members.","ref":"couchbeam.html#delete_docs/3"},{"type":"function","title":"couchbeam.design_info/2","doc":"","ref":"couchbeam.html#design_info/2"},{"type":"type","title":"couchbeam.doc/0","doc":"","ref":"couchbeam.html#t:doc/0"},{"type":"function","title":"couchbeam.doc_exists/2","doc":"test if doc with uuid exists in the given db","ref":"couchbeam.html#doc_exists/2"},{"type":"opaque","title":"couchbeam.doc_stream/0","doc":"","ref":"couchbeam.html#t:doc_stream/0"},{"type":"type","title":"couchbeam.ejson_object/0","doc":"","ref":"couchbeam.html#t:ejson_object/0"},{"type":"function","title":"couchbeam.end_doc_stream/1","doc":"stop to receive the multipart response of the doc api and close the connection.","ref":"couchbeam.html#end_doc_stream/1"},{"type":"function","title":"couchbeam.ensure_full_commit/1","doc":"Equivalent to ensure_full_commit(Db, []) . commit all docs in memory","ref":"couchbeam.html#ensure_full_commit/1"},{"type":"function","title":"couchbeam.ensure_full_commit/2","doc":"commit all docs in memory","ref":"couchbeam.html#ensure_full_commit/2"},{"type":"function","title":"couchbeam.fetch_attachment/3","doc":"Equivalent to fetch_attachment(Db, DocId, Name, []) . fetch a document attachment","ref":"couchbeam.html#fetch_attachment/3"},{"type":"function","title":"couchbeam.fetch_attachment/4","doc":"fetch a document attachment Options are stream : to start streaming an attachment. the function return {ok, Ref} where is a ref to the attachment Other options that can be sent using the REST API","ref":"couchbeam.html#fetch_attachment/4"},{"type":"function","title":"couchbeam.find/3","doc":"","ref":"couchbeam.html#find/3"},{"type":"function","title":"couchbeam.get_missing_revs/2","doc":"get missing revisions","ref":"couchbeam.html#get_missing_revs/2"},{"type":"function","title":"couchbeam.get_uuid/1","doc":"Get one uuid from the server","ref":"couchbeam.html#get_uuid/1"},{"type":"function","title":"couchbeam.get_uuids/2","doc":"Get a list of uuids from the server","ref":"couchbeam.html#get_uuids/2"},{"type":"function","title":"couchbeam.lookup_doc_rev/2","doc":"get the last revision of the document","ref":"couchbeam.html#lookup_doc_rev/2"},{"type":"function","title":"couchbeam.lookup_doc_rev/3","doc":"","ref":"couchbeam.html#lookup_doc_rev/3"},{"type":"type","title":"couchbeam.mp_attachment/0","doc":"","ref":"couchbeam.html#t:mp_attachment/0"},{"type":"type","title":"couchbeam.mp_attachments/0","doc":"","ref":"couchbeam.html#t:mp_attachments/0"},{"type":"function","title":"couchbeam.open_db/2","doc":"Equivalent to open_db(Server, DbName, []) . Create a client for connection to a database","ref":"couchbeam.html#open_db/2"},{"type":"function","title":"couchbeam.open_db/3","doc":"Create a client for connection to a database -> {ok, db()}","ref":"couchbeam.html#open_db/3"},{"type":"function","title":"couchbeam.open_doc/2","doc":"Equivalent to open_doc(Db, DocId, []) . open a document","ref":"couchbeam.html#open_doc/2"},{"type":"function","title":"couchbeam.open_doc/3","doc":"open a document Params is a list of query argument. Have a look in CouchDb API -> {ok, Doc}|{error, Error}","ref":"couchbeam.html#open_doc/3"},{"type":"function","title":"couchbeam.open_or_create_db/2","doc":"Equivalent to open_or_create_db(Server, DbName, [], []) . Create a client for connecting to a database and create the database if needed.","ref":"couchbeam.html#open_or_create_db/2"},{"type":"function","title":"couchbeam.open_or_create_db/3","doc":"Equivalent to open_or_create_db(Server, DbName, Options, []) . Create a client for connecting to a database and create the database if needed.","ref":"couchbeam.html#open_or_create_db/3"},{"type":"function","title":"couchbeam.open_or_create_db/4","doc":"Create a client for connecting to a database and create the database if needed.","ref":"couchbeam.html#open_or_create_db/4"},{"type":"function","title":"couchbeam.put_attachment/4","doc":"Equivalent to put_attachment(Db, DocId, Name, Body, []) . put an attachment","ref":"couchbeam.html#put_attachment/4"},{"type":"function","title":"couchbeam.put_attachment/5","doc":"put an attachment Body::body(), Option::optionList()) -> {ok, iolist()} optionList() = [option()] option() = {rev, string()} | {content_type, string()} | {content_length, string()} body() = [] | string() | binary() | fun_arity_0() | {fun_arity_1(), initial_state(), stream} initial_state() = term()","ref":"couchbeam.html#put_attachment/5"},{"type":"function","title":"couchbeam.replicate/2","doc":"Handle replication. Pass a map containing all information. It allows passing authentication info, etc. RepObj = #{\n <<"source">> => <<"sourcedb">>,\n <<"target">> => <<"targetdb">>,\n <<"create_target">> => true\n }.\n replicate(Server, RepObj). -> {ok, Result}|{error, Error}","ref":"couchbeam.html#replicate/2"},{"type":"function","title":"couchbeam.replicate/3","doc":"Handle replication. -> {ok, Result}|{error, Error}","ref":"couchbeam.html#replicate/3"},{"type":"function","title":"couchbeam.replicate/4","doc":"handle Replication. Allows to pass options with source and target. Source and target can be either simple URI strings or complex document structures with authentication. Options is a Json object. ex: %% Simple URI replication\n Options = [{<<"create_target">>, true}]},\n couchbeam:replicate(S, "testdb", "testdb2", Options).\n \n %% Complex replication with authentication\n Source = "http://user:pass@remote.com:5984/db",\n Target = #{\n <<"url">> => <<"http://localhost:5984/target_db">>,\n <<"auth">> => #{\n <<"basic">> => #{<<"username">> => <<"user">>,\n <<"password">> => <<"pass">>}\n }\n },\n couchbeam:replicate(S, Source, Target, [{<<"continuous">>, true}]).","ref":"couchbeam.html#replicate/4"},{"type":"function","title":"couchbeam.save_doc/2","doc":"Equivalent to save_doc(Db, Doc, []) . save a document","ref":"couchbeam.html#save_doc/2"},{"type":"function","title":"couchbeam.save_doc/3","doc":"save a *document A document is a Json object like this one: #{\n <<"_id">> => <<"myid">>,\n <<"title">> => <<"test">>\n } Options are arguments passed to the request. This function return a new document with last revision and a docid. If _id isn't specified in document it will be created. Id is created by extracting an uuid from the couchdb node.","ref":"couchbeam.html#save_doc/3"},{"type":"function","title":"couchbeam.save_doc/4","doc":"save a *document with all its attacjments A document is a Json object like this one: #{\n <<"_id">> => <<"myid">>,\n <<"title">> => <<"test">>\n } Options are arguments passed to the request. This function return a new document with last revision and a docid. If _id isn't specified in document it will be created. Id is created by extracting an uuid from the couchdb node. If the attachments is not empty, the doc will be sent as multipart. Attachments are passed as a list of the following tuples: - {Name :: binary(), Bin :: binary()} - {Name :: binary(), Bin :: binary(), Encoding :: binary()} - { Name :: binary(), Bin :: binary(), Type :: binary(), Encoding :: binary()} - { Name :: binary(), {file, Path :: string()}} - { Name :: binary(), {file, Path :: string()}, Encoding :: binary()} - { Name :: binary(), Fun :: fun(), Length :: integer()} - { Name :: binary(), Fun :: fun(), Length :: integer(), Encoding :: binary()} - {Name :: binary(), Fun :: fun(), Length :: integer(), Type :: binary(), Encoding :: binary()} - { Name :: binary(), {Fun :: fun(), Acc :: any()}, Length :: integer()} - { Name :: binary(), {Fun :: fun(), Acc :: any()}, Length :: integer(), Encoding :: binary()} - { Name :: binary(), {Fun :: fun(), Acc :: any()}, Length :: integer(), Type :: binary(), Encoding :: binary()}. where Type` is the content-type of the attachments (detected in other case) and `Encoding` the encoding of the attachments: `<<\"identity\">> if normal or <<\"gzip\">> if the attachments is gzipped.","ref":"couchbeam.html#save_doc/4"},{"type":"function","title":"couchbeam.save_docs/2","doc":"Equivalent to save_docs(Db, Docs, []) . save a list of documents","ref":"couchbeam.html#save_docs/2"},{"type":"function","title":"couchbeam.save_docs/3","doc":"save a list of documents","ref":"couchbeam.html#save_docs/3"},{"type":"function","title":"couchbeam.send_attachment/2","doc":"send an attachment chunk Msg could be Data, eof to stop sending.","ref":"couchbeam.html#send_attachment/2"},{"type":"type","title":"couchbeam.server/0","doc":"","ref":"couchbeam.html#t:server/0"},{"type":"function","title":"couchbeam.server_connection/0","doc":"Equivalent to server_connection(URL, Options) . Create a server for connectiong to a CouchDB node","ref":"couchbeam.html#server_connection/0"},{"type":"function","title":"couchbeam.server_connection/1","doc":"","ref":"couchbeam.html#server_connection/1"},{"type":"function","title":"couchbeam.server_connection/2","doc":"Equivalent to server_connection(Host, Port, \"\", []) . Create a server for connectiong to a CouchDB node","ref":"couchbeam.html#server_connection/2"},{"type":"function","title":"couchbeam.server_connection/4","doc":"Create a server for connectiong to a CouchDB node Connections are made to: http://Host:PortPrefix If ssl is set https is used. For a description of SSL Options, look in the ssl manpage.","ref":"couchbeam.html#server_connection/4"},{"type":"function","title":"couchbeam.server_info/1","doc":"Get Information from the server","ref":"couchbeam.html#server_info/1"},{"type":"function","title":"couchbeam.stream_attachment/1","doc":"fetch an attachment chunk. Use this function when you pass the stream option to the couchbeam:fetch_attachment/4 function. This function return the following response: done You got all the attachment {ok, binary()} Part of the attachment {error, term()} n error occurred","ref":"couchbeam.html#stream_attachment/1"},{"type":"function","title":"couchbeam.stream_doc/1","doc":"stream the multipart response of the doc API. Use this function when you get {ok, {multipart, State}} from the function couchbeam:open_doc/3 .","ref":"couchbeam.html#stream_doc/1"},{"type":"function","title":"couchbeam.view_cleanup/1","doc":"","ref":"couchbeam.html#view_cleanup/1"},{"type":"module","title":"couchbeam_app","doc":"","ref":"couchbeam_app.html"},{"type":"function","title":"couchbeam_app.start/2","doc":"","ref":"couchbeam_app.html#start/2"},{"type":"function","title":"couchbeam_app.stop/1","doc":"","ref":"couchbeam_app.html#stop/1"},{"type":"module","title":"couchbeam_attachments","doc":"This module contains utilities to manage attachments","ref":"couchbeam_attachments.html"},{"type":"function","title":"couchbeam_attachments.add_inline/3","doc":"add attachment to a doc and encode it. Give possibility to send attachments inline.","ref":"couchbeam_attachments.html#add_inline/3"},{"type":"function","title":"couchbeam_attachments.add_inline/4","doc":"add attachment to a doc and encode it with ContentType fixed.","ref":"couchbeam_attachments.html#add_inline/4"},{"type":"function","title":"couchbeam_attachments.add_stub/3","doc":"","ref":"couchbeam_attachments.html#add_stub/3"},{"type":"function","title":"couchbeam_attachments.delete_inline/2","doc":"delete an attachment record in doc. This is different from delete_attachment change is only applied in Doc object. Save_doc should be save to save changes.","ref":"couchbeam_attachments.html#delete_inline/2"},{"type":"type","title":"couchbeam_attachments.doc/0","doc":"","ref":"couchbeam_attachments.html#t:doc/0"},{"type":"type","title":"couchbeam_attachments.ejson_object/0","doc":"","ref":"couchbeam_attachments.html#t:ejson_object/0"},{"type":"module","title":"couchbeam_changes","doc":"","ref":"couchbeam_changes.html"},{"type":"function","title":"couchbeam_changes.cancel_stream/1","doc":"","ref":"couchbeam_changes.html#cancel_stream/1"},{"type":"type","title":"couchbeam_changes.changes_option/0","doc":"","ref":"couchbeam_changes.html#t:changes_option/0"},{"type":"type","title":"couchbeam_changes.changes_options/0","doc":"","ref":"couchbeam_changes.html#t:changes_options/0"},{"type":"type","title":"couchbeam_changes.db/0","doc":"","ref":"couchbeam_changes.html#t:db/0"},{"type":"function","title":"couchbeam_changes.follow/1","doc":"","ref":"couchbeam_changes.html#follow/1"},{"type":"function","title":"couchbeam_changes.follow/2","doc":"Stream changes to a pid Db : a db record Client : pid or callback where to send changes events where events are The pid receive these events: {change, StartRef, {done, Lastseq::integer()} Connection terminated or you got all changes {change, StartRef, Row :: ejson_object()} Line of change {error, LastSeq::integer(), Msg::term()} Got an error, connection is closed when an error happend. LastSeq is the last sequence of changes. While the callbac could be like: fun({done, LastSeq}) ->\n ok;\n fun({done, LastSeq}) ->\n ok;\n fun({done, LastSeq}) ->\n ok. >Options :: changes_stream_options() [continuous\n | longpoll\n | normal\n | include_docs\n | {since, integer() | now}\n | {timeout, integer()}\n | heartbeat | {heartbeat, integer()}\n | {filter, string()} | {filter, string(), list({string(), string() | integer()})}\n | {view, string()},\n | {docids, list))},\n | {stream_to, pid()},\n | {async, once | normal}] continuous | longpoll | normal : set the type of changes feed to get include_doc : if you want to include the doc in the line of change {timeout, Timeout::integer()} : timeout heartbeat | {heartbeat, Heartbeat::integer()} : set couchdb to send a heartbeat to maintain connection open {filter, FilterName} | {filter, FilterName, Args::list({key, value})} : set the filter to use with optional arguments {view, ViewName} : use a view function as filter. Note that it requires to set filter special value \"_view\" to enable this feature. > {stream_to, Pid} : the pid where the changes will be sent, by default the current pid. Used for continuous and longpoll connections Return {ok, StartRef, ChangesPid} or {error, Error}. Ref can be used to disctint all changes from this pid. ChangesPid is the pid of the changes loop process. Can be used to monitor it or kill it when needed.","ref":"couchbeam_changes.html#follow/2"},{"type":"function","title":"couchbeam_changes.follow_once/1","doc":"","ref":"couchbeam_changes.html#follow_once/1"},{"type":"function","title":"couchbeam_changes.follow_once/2","doc":"fetch all changes at once using a normal or longpoll connections. Db : a db record Options :: changes_options() [\n | longpoll\n | normal\n | include_docs\n | {since, integer() | now}\n | {timeout, integer()}\n | heartbeat | {heartbeat, integer()}\n | {filter, string()}\n | {filter, string(), list({string(), string() | integer()})}\n | {docids, list()))},\n | {stream_to, pid()}\n ] longpoll | normal : set the type of changes feed to get include_docs : if you want to include the doc in the line of change {timeout, Timeout::integer()} : timeout heartbeat | {heartbeat, Heartbeat::integer()} : set couchdb to send a heartbeat to maintain connection open {filter, FilterName} | {filter, FilterName, Args::list({key, value}) : set the filter to use with optional arguments {view, ViewName} : use a view function as filter. Note that it requires to set filter special value \"_view\" to enable this feature. Result: {ok, LastSeq::integer(), Rows::list()} or {error, LastSeq, Error} . LastSeq is the last sequence of changes.","ref":"couchbeam_changes.html#follow_once/2"},{"type":"type","title":"couchbeam_changes.server/0","doc":"","ref":"couchbeam_changes.html#t:server/0"},{"type":"function","title":"couchbeam_changes.stream_next/1","doc":"","ref":"couchbeam_changes.html#stream_next/1"},{"type":"module","title":"couchbeam_changes_stream","doc":"","ref":"couchbeam_changes_stream.html"},{"type":"function","title":"couchbeam_changes_stream.init_stream/5","doc":"","ref":"couchbeam_changes_stream.html#init_stream/5"},{"type":"function","title":"couchbeam_changes_stream.maybe_continue/1","doc":"","ref":"couchbeam_changes_stream.html#maybe_continue/1"},{"type":"function","title":"couchbeam_changes_stream.start_link/4","doc":"","ref":"couchbeam_changes_stream.html#start_link/4"},{"type":"function","title":"couchbeam_changes_stream.system_code_change/4","doc":"","ref":"couchbeam_changes_stream.html#system_code_change/4"},{"type":"function","title":"couchbeam_changes_stream.system_continue/3","doc":"","ref":"couchbeam_changes_stream.html#system_continue/3"},{"type":"function","title":"couchbeam_changes_stream.system_terminate/4","doc":"","ref":"couchbeam_changes_stream.html#system_terminate/4"},{"type":"function","title":"couchbeam_changes_stream.wait_reconnect/1","doc":"","ref":"couchbeam_changes_stream.html#wait_reconnect/1"},{"type":"module","title":"couchbeam_changes_sup","doc":"","ref":"couchbeam_changes_sup.html"},{"type":"function","title":"couchbeam_changes_sup.init/1","doc":"","ref":"couchbeam_changes_sup.html#init/1"},{"type":"function","title":"couchbeam_changes_sup.start_link/0","doc":"","ref":"couchbeam_changes_sup.html#start_link/0"},{"type":"module","title":"couchbeam_doc","doc":"","ref":"couchbeam_doc.html"},{"type":"function","title":"couchbeam_doc.delete_value/2","doc":"Deletes all entries associated with Key in json object.","ref":"couchbeam_doc.html#delete_value/2"},{"type":"type","title":"couchbeam_doc.doc/0","doc":"","ref":"couchbeam_doc.html#t:doc/0"},{"type":"type","title":"couchbeam_doc.ejson_array/0","doc":"","ref":"couchbeam_doc.html#t:ejson_array/0"},{"type":"type","title":"couchbeam_doc.ejson_number/0","doc":"","ref":"couchbeam_doc.html#t:ejson_number/0"},{"type":"type","title":"couchbeam_doc.ejson_object/0","doc":"","ref":"couchbeam_doc.html#t:ejson_object/0"},{"type":"type","title":"couchbeam_doc.ejson_string/0","doc":"","ref":"couchbeam_doc.html#t:ejson_string/0"},{"type":"type","title":"couchbeam_doc.ejson_term/0","doc":"","ref":"couchbeam_doc.html#t:ejson_term/0"},{"type":"function","title":"couchbeam_doc.extend/2","doc":"extend a jsonobject by a property, list of property or another jsonobject","ref":"couchbeam_doc.html#extend/2"},{"type":"function","title":"couchbeam_doc.extend/3","doc":"extend a jsonobject by key, value","ref":"couchbeam_doc.html#extend/3"},{"type":"function","title":"couchbeam_doc.get_id/1","doc":"get document id.","ref":"couchbeam_doc.html#get_id/1"},{"type":"function","title":"couchbeam_doc.get_idrev/1","doc":"get a tuple containing docucment id and revision.","ref":"couchbeam_doc.html#get_idrev/1"},{"type":"function","title":"couchbeam_doc.get_rev/1","doc":"get document revision.","ref":"couchbeam_doc.html#get_rev/1"},{"type":"function","title":"couchbeam_doc.get_value/2","doc":"Returns the value of a simple key/value property in json object Equivalent to get_value(Key, JsonObj, undefined).","ref":"couchbeam_doc.html#get_value/2"},{"type":"function","title":"couchbeam_doc.get_value/3","doc":"Returns the value of a simple key/value property in json object function from erlang_couchdb","ref":"couchbeam_doc.html#get_value/3"},{"type":"function","title":"couchbeam_doc.is_saved/1","doc":"If document have been saved (revision is defined) return true, else, return false.","ref":"couchbeam_doc.html#is_saved/1"},{"type":"function","title":"couchbeam_doc.set_value/3","doc":"set a value for a key in jsonobj. If key exists it will be updated.","ref":"couchbeam_doc.html#set_value/3"},{"type":"function","title":"couchbeam_doc.take_value/2","doc":"Returns the value of a simple key/value property in json object and deletes it form json object Equivalent to take_value(Key, JsonObj, undefined).","ref":"couchbeam_doc.html#take_value/2"},{"type":"function","title":"couchbeam_doc.take_value/3","doc":"Returns the value of a simple key/value property in json object and deletes it from json object","ref":"couchbeam_doc.html#take_value/3"},{"type":"module","title":"couchbeam_ejson","doc":"","ref":"couchbeam_ejson.html"},{"type":"function","title":"couchbeam_ejson.decode/1","doc":"decode a binary to an EJSON term. Throw an exception if there is any error.","ref":"couchbeam_ejson.html#decode/1"},{"type":"type","title":"couchbeam_ejson.ejson/0","doc":"","ref":"couchbeam_ejson.html#t:ejson/0"},{"type":"type","title":"couchbeam_ejson.ejson_array/0","doc":"","ref":"couchbeam_ejson.html#t:ejson_array/0"},{"type":"type","title":"couchbeam_ejson.ejson_number/0","doc":"","ref":"couchbeam_ejson.html#t:ejson_number/0"},{"type":"type","title":"couchbeam_ejson.ejson_object/0","doc":"","ref":"couchbeam_ejson.html#t:ejson_object/0"},{"type":"type","title":"couchbeam_ejson.ejson_string/0","doc":"","ref":"couchbeam_ejson.html#t:ejson_string/0"},{"type":"type","title":"couchbeam_ejson.ejson_term/0","doc":"","ref":"couchbeam_ejson.html#t:ejson_term/0"},{"type":"function","title":"couchbeam_ejson.encode/1","doc":"encode an erlang term to JSON. Throw an exception if there is any error.","ref":"couchbeam_ejson.html#encode/1"},{"type":"function","title":"couchbeam_ejson.post_decode/1","doc":"","ref":"couchbeam_ejson.html#post_decode/1"},{"type":"module","title":"couchbeam_httpc","doc":"","ref":"couchbeam_httpc.html"},{"type":"type","title":"couchbeam_httpc.db/0","doc":"","ref":"couchbeam_httpc.html#t:db/0"},{"type":"function","title":"couchbeam_httpc.db_request/5","doc":"","ref":"couchbeam_httpc.html#db_request/5"},{"type":"function","title":"couchbeam_httpc.db_request/6","doc":"","ref":"couchbeam_httpc.html#db_request/6"},{"type":"function","title":"couchbeam_httpc.db_resp/2","doc":"","ref":"couchbeam_httpc.html#db_resp/2"},{"type":"function","title":"couchbeam_httpc.db_url/1","doc":"","ref":"couchbeam_httpc.html#db_url/1"},{"type":"function","title":"couchbeam_httpc.doc_url/2","doc":"","ref":"couchbeam_httpc.html#doc_url/2"},{"type":"function","title":"couchbeam_httpc.json_body/1","doc":"","ref":"couchbeam_httpc.html#json_body/1"},{"type":"function","title":"couchbeam_httpc.make_headers/4","doc":"","ref":"couchbeam_httpc.html#make_headers/4"},{"type":"function","title":"couchbeam_httpc.maybe_oauth_header/4","doc":"","ref":"couchbeam_httpc.html#maybe_oauth_header/4"},{"type":"function","title":"couchbeam_httpc.request/5","doc":"","ref":"couchbeam_httpc.html#request/5"},{"type":"type","title":"couchbeam_httpc.server/0","doc":"","ref":"couchbeam_httpc.html#t:server/0"},{"type":"function","title":"couchbeam_httpc.server_url/1","doc":"Asemble the server URL for the given client","ref":"couchbeam_httpc.html#server_url/1"},{"type":"module","title":"couchbeam_sup","doc":"","ref":"couchbeam_sup.html"},{"type":"function","title":"couchbeam_sup.init/1","doc":"","ref":"couchbeam_sup.html#init/1"},{"type":"function","title":"couchbeam_sup.start_link/0","doc":"","ref":"couchbeam_sup.html#start_link/0"},{"type":"module","title":"couchbeam_util","doc":"","ref":"couchbeam_util.html"},{"type":"function","title":"couchbeam_util.binary_env/2","doc":"","ref":"couchbeam_util.html#binary_env/2"},{"type":"function","title":"couchbeam_util.dbname/1","doc":"","ref":"couchbeam_util.html#dbname/1"},{"type":"function","title":"couchbeam_util.deprecated/3","doc":"","ref":"couchbeam_util.html#deprecated/3"},{"type":"function","title":"couchbeam_util.encode_att_name/1","doc":"","ref":"couchbeam_util.html#encode_att_name/1"},{"type":"function","title":"couchbeam_util.encode_docid1/1","doc":"","ref":"couchbeam_util.html#encode_docid1/1"},{"type":"function","title":"couchbeam_util.encode_docid/1","doc":"","ref":"couchbeam_util.html#encode_docid/1"},{"type":"function","title":"couchbeam_util.encode_docid_noop/1","doc":"","ref":"couchbeam_util.html#encode_docid_noop/1"},{"type":"function","title":"couchbeam_util.encode_query/1","doc":"Encode needed query parameter values for JSON","ref":"couchbeam_util.html#encode_query/1"},{"type":"function","title":"couchbeam_util.encode_query_value/2","doc":"Encode value in JSON if needed depending on the key","ref":"couchbeam_util.html#encode_query_value/2"},{"type":"function","title":"couchbeam_util.force_param/3","doc":"Replace a value in a property list","ref":"couchbeam_util.html#force_param/3"},{"type":"function","title":"couchbeam_util.get_app_env/2","doc":"","ref":"couchbeam_util.html#get_app_env/2"},{"type":"function","title":"couchbeam_util.get_value/2","doc":"Emulate proplists:get_value/2,3 for property lists but use faster lists:keyfind/3","ref":"couchbeam_util.html#get_value/2"},{"type":"function","title":"couchbeam_util.get_value/3","doc":"","ref":"couchbeam_util.html#get_value/3"},{"type":"function","title":"couchbeam_util.oauth_header/3","doc":"","ref":"couchbeam_util.html#oauth_header/3"},{"type":"function","title":"couchbeam_util.parse_options/1","doc":"make view options a list","ref":"couchbeam_util.html#parse_options/1"},{"type":"function","title":"couchbeam_util.parse_options/2","doc":"","ref":"couchbeam_util.html#parse_options/2"},{"type":"function","title":"couchbeam_util.propmerge1/2","doc":"Update a property list with values of the second. In case the same key is in both lists, the value from the first is kept.","ref":"couchbeam_util.html#propmerge1/2"},{"type":"function","title":"couchbeam_util.propmerge/3","doc":"Merge two property lists (lists of {Key,Value}). All the Key - Value pairs from both lists are included in the new list. If a key occurs in both dictionaries then Fun is called with the key and both values to return a new value. This a wreapper around dict:merge","ref":"couchbeam_util.html#propmerge/3"},{"type":"function","title":"couchbeam_util.proxy_header/3","doc":"","ref":"couchbeam_util.html#proxy_header/3"},{"type":"function","title":"couchbeam_util.proxy_token/2","doc":"","ref":"couchbeam_util.html#proxy_token/2"},{"type":"function","title":"couchbeam_util.shutdown_sync/1","doc":"","ref":"couchbeam_util.html#shutdown_sync/1"},{"type":"function","title":"couchbeam_util.start_app_deps/1","doc":"Start depedent applications of App.","ref":"couchbeam_util.html#start_app_deps/1"},{"type":"function","title":"couchbeam_util.to_atom/1","doc":"","ref":"couchbeam_util.html#to_atom/1"},{"type":"function","title":"couchbeam_util.to_binary/1","doc":"","ref":"couchbeam_util.html#to_binary/1"},{"type":"function","title":"couchbeam_util.to_integer/1","doc":"","ref":"couchbeam_util.html#to_integer/1"},{"type":"function","title":"couchbeam_util.to_list/1","doc":"","ref":"couchbeam_util.html#to_list/1"},{"type":"module","title":"couchbeam_uuids","doc":"","ref":"couchbeam_uuids.html"},{"type":"function","title":"couchbeam_uuids.code_change/3","doc":"","ref":"couchbeam_uuids.html#code_change/3"},{"type":"function","title":"couchbeam_uuids.get_uuids/2","doc":"Get a list of uuids from the server","ref":"couchbeam_uuids.html#get_uuids/2"},{"type":"function","title":"couchbeam_uuids.handle_call/3","doc":"","ref":"couchbeam_uuids.html#handle_call/3"},{"type":"function","title":"couchbeam_uuids.handle_cast/2","doc":"","ref":"couchbeam_uuids.html#handle_cast/2"},{"type":"function","title":"couchbeam_uuids.handle_info/2","doc":"","ref":"couchbeam_uuids.html#handle_info/2"},{"type":"function","title":"couchbeam_uuids.init/1","doc":"","ref":"couchbeam_uuids.html#init/1"},{"type":"function","title":"couchbeam_uuids.random/0","doc":"return a random uuid","ref":"couchbeam_uuids.html#random/0"},{"type":"type","title":"couchbeam_uuids.server/0","doc":"","ref":"couchbeam_uuids.html#t:server/0"},{"type":"function","title":"couchbeam_uuids.start_link/0","doc":"Starts the couchbeam process linked to the calling process. Usually invoked by the supervisor couchbeam_sup","ref":"couchbeam_uuids.html#start_link/0"},{"type":"function","title":"couchbeam_uuids.terminate/2","doc":"","ref":"couchbeam_uuids.html#terminate/2"},{"type":"function","title":"couchbeam_uuids.utc_random/0","doc":"return a random uuid based on time","ref":"couchbeam_uuids.html#utc_random/0"},{"type":"module","title":"couchbeam_view","doc":"","ref":"couchbeam_view.html"},{"type":"function","title":"couchbeam_view.all/1","doc":"Equivalent to fetch(Db, all_docs, []) . fetch all docs","ref":"couchbeam_view.html#all/1"},{"type":"function","title":"couchbeam_view.all/2","doc":"Equivalent to fetch(Db, all_docs, Options) . fetch all docs","ref":"couchbeam_view.html#all/2"},{"type":"function","title":"couchbeam_view.cancel_stream/1","doc":"","ref":"couchbeam_view.html#cancel_stream/1"},{"type":"function","title":"couchbeam_view.count/1","doc":"Equivalent to count(Db, all_docs, []) .","ref":"couchbeam_view.html#count/1"},{"type":"function","title":"couchbeam_view.count/2","doc":"Equivalent to count(Db, ViewName, []) .","ref":"couchbeam_view.html#count/2"},{"type":"function","title":"couchbeam_view.count/3","doc":"count number of doc in a view (or all docs)","ref":"couchbeam_view.html#count/3"},{"type":"type","title":"couchbeam_view.db/0","doc":"","ref":"couchbeam_view.html#t:db/0"},{"type":"type","title":"couchbeam_view.design_name/0","doc":"","ref":"couchbeam_view.html#t:design_name/0"},{"type":"type","title":"couchbeam_view.ejson_object/0","doc":"","ref":"couchbeam_view.html#t:ejson_object/0"},{"type":"function","title":"couchbeam_view.fetch/1","doc":"Equivalent to fetch(Db, all_docs, []) .","ref":"couchbeam_view.html#fetch/1"},{"type":"function","title":"couchbeam_view.fetch/2","doc":"Equivalent to fetch(Db, ViewName, []) .","ref":"couchbeam_view.html#fetch/2"},{"type":"function","title":"couchbeam_view.fetch/3","doc":"Collect view results Db: a db record ViewName: 'all_docs' to get all docs or {DesignName, ViewName} Options :: view_options() [{key, binary()}\n | {start_docid, binary()} | {startkey_docid, binary()}\n | {end_docid, binary()} | {endkey_docid, binary()}\n | {start_key, binary()} | {end_key, binary()}\n | {limit, integer()}\n | {stale, stale()}\n | descending\n | {skip, integer()}\n | group | {group_level, integer()}\n | {inclusive_end, boolean()} | {reduce, boolean()} | reduce | include_docs | conflicts\n | {keys, list(binary())}\n | async_query See couchbeam_view:stream/3 for more information about options. Return: {ok, Rows} or {error, Error}","ref":"couchbeam_view.html#fetch/3"},{"type":"function","title":"couchbeam_view.first/1","doc":"","ref":"couchbeam_view.html#first/1"},{"type":"function","title":"couchbeam_view.first/2","doc":"Equivalent to first(Db, ViewName, []) .","ref":"couchbeam_view.html#first/2"},{"type":"function","title":"couchbeam_view.first/3","doc":"get first result of a view Db: a db record ViewName: 'all_docs' to get all docs or {DesignName, ViewName} Options :: view_options() [{key, binary()}\n | {start_docid, binary()} | {startkey_docid, binary()}\n | {end_docid, binary()} | {endkey_docid, binary()}\n | {start_key, binary()} | {end_key, binary()}\n | {limit, integer()}\n | {stale, stale()}\n | descending\n | {skip, integer()}\n | group | {group_level, integer()}\n | {inclusive_end, boolean()} | {reduce, boolean()} | reduce | include_docs | conflicts\n | {keys, list(binary())} See couchbeam_view:stream/3 for more information about options. Return: {ok, Row} or {error, Error}","ref":"couchbeam_view.html#first/3"},{"type":"function","title":"couchbeam_view.fold/4","doc":"Equivalent to fold(Function, Acc, Db, ViewName, []) .","ref":"couchbeam_view.html#fold/4"},{"type":"function","title":"couchbeam_view.fold/5","doc":"call Function(Row, AccIn) on succesive row, starting with AccIn == Acc. Function/2 must return a new list accumultator or the atom done to stop fetching results. Acc0 is returned if the list is empty. For example: couchbeam_view:fold(fun(Row, Acc) -> [Row|Acc] end, [], Db, 'all_docs').","ref":"couchbeam_view.html#fold/5"},{"type":"function","title":"couchbeam_view.foreach/3","doc":"Equivalent to foreach(Function, Db, ViewName, []) .","ref":"couchbeam_view.html#foreach/3"},{"type":"function","title":"couchbeam_view.foreach/4","doc":"call Function(Row) on succesive row. Example: couchbeam_view:foreach(fun(Row) -> io:format("got row ~p~n", [Row]) end, Db, 'all_docs').","ref":"couchbeam_view.html#foreach/4"},{"type":"function","title":"couchbeam_view.parse_view_options/1","doc":"parse view options","ref":"couchbeam_view.html#parse_view_options/1"},{"type":"type","title":"couchbeam_view.server/0","doc":"","ref":"couchbeam_view.html#t:server/0"},{"type":"function","title":"couchbeam_view.show/2","doc":"","ref":"couchbeam_view.html#show/2"},{"type":"function","title":"couchbeam_view.show/3","doc":"","ref":"couchbeam_view.html#show/3"},{"type":"function","title":"couchbeam_view.show/4","doc":"","ref":"couchbeam_view.html#show/4"},{"type":"type","title":"couchbeam_view.show_option/0","doc":"example: \"foo=bar&baz=biz\"","ref":"couchbeam_view.html#t:show_option/0"},{"type":"type","title":"couchbeam_view.show_options/0","doc":"","ref":"couchbeam_view.html#t:show_options/0"},{"type":"type","title":"couchbeam_view.stale/0","doc":"","ref":"couchbeam_view.html#t:stale/0"},{"type":"function","title":"couchbeam_view.stream/2","doc":"Equivalent to stream(Db, ViewName, []) .","ref":"couchbeam_view.html#stream/2"},{"type":"function","title":"couchbeam_view.stream/3","doc":"stream view results to a pid Db: a db record ViewName: 'all_docs' to get all docs or {DesignName, ViewName} Client receives messages: - {row, StartRef, done} All rows have been fetched - {row, StartRef, Row :: ejson_object()} A row in the view - {error, StartRef, Error} An error occurred; stream closed Options include (see couchbeam_view:parse_view_options/1): - {key, Key} - {start_docid, DocId} | {startkey_docid, DocId} - {end_docid, DocId} | {endkey_docid, DocId} - {start_key, Key} | {end_key, Key} - {limit, N} - {stale, ok | update_after | false} - descending | {skip, N} - group | {group_level, integer()} - reduce | {reduce, boolean()} - include_docs | conflicts | {inclusive_end, boolean()} - {keys, [Key]} - {stream_to, Pid}","ref":"couchbeam_view.html#stream/3"},{"type":"function","title":"couchbeam_view.stream_next/1","doc":"","ref":"couchbeam_view.html#stream_next/1"},{"type":"type","title":"couchbeam_view.view_name/0","doc":"","ref":"couchbeam_view.html#t:view_name/0"},{"type":"type","title":"couchbeam_view.view_option/0","doc":"","ref":"couchbeam_view.html#t:view_option/0"},{"type":"type","title":"couchbeam_view.view_options/0","doc":"","ref":"couchbeam_view.html#t:view_options/0"},{"type":"type","title":"couchbeam_view.view_query_args/0","doc":"","ref":"couchbeam_view.html#t:view_query_args/0"},{"type":"module","title":"couchbeam_view_stream","doc":"","ref":"couchbeam_view_stream.html"},{"type":"function","title":"couchbeam_view_stream.init_stream/5","doc":"","ref":"couchbeam_view_stream.html#init_stream/5"},{"type":"function","title":"couchbeam_view_stream.maybe_continue/1","doc":"","ref":"couchbeam_view_stream.html#maybe_continue/1"},{"type":"function","title":"couchbeam_view_stream.start_link/4","doc":"","ref":"couchbeam_view_stream.html#start_link/4"},{"type":"function","title":"couchbeam_view_stream.system_code_change/4","doc":"","ref":"couchbeam_view_stream.html#system_code_change/4"},{"type":"function","title":"couchbeam_view_stream.system_continue/3","doc":"","ref":"couchbeam_view_stream.html#system_continue/3"},{"type":"function","title":"couchbeam_view_stream.system_terminate/4","doc":"","ref":"couchbeam_view_stream.html#system_terminate/4"},{"type":"module","title":"couchbeam_view_sup","doc":"","ref":"couchbeam_view_sup.html"},{"type":"function","title":"couchbeam_view_sup.init/1","doc":"","ref":"couchbeam_view_sup.html#init/1"},{"type":"function","title":"couchbeam_view_sup.start_link/0","doc":"","ref":"couchbeam_view_sup.html#start_link/0"},{"type":"behaviour","title":"gen_changes","doc":"gen_changes CouchDB continuous changes consumer behavior This behaviour allows you to create easily a server that consume Couchdb continuous changes","ref":"gen_changes.html"},{"type":"function","title":"gen_changes.behaviour_info/1","doc":"","ref":"gen_changes.html#behaviour_info/1"},{"type":"function","title":"gen_changes.call/2","doc":"","ref":"gen_changes.html#call/2"},{"type":"function","title":"gen_changes.call/3","doc":"","ref":"gen_changes.html#call/3"},{"type":"function","title":"gen_changes.cast/2","doc":"","ref":"gen_changes.html#cast/2"},{"type":"function","title":"gen_changes.code_change/3","doc":"","ref":"gen_changes.html#code_change/3"},{"type":"function","title":"gen_changes.get_seq/1","doc":"","ref":"gen_changes.html#get_seq/1"},{"type":"function","title":"gen_changes.handle_call/3","doc":"","ref":"gen_changes.html#handle_call/3"},{"type":"function","title":"gen_changes.handle_cast/2","doc":"","ref":"gen_changes.html#handle_cast/2"},{"type":"function","title":"gen_changes.handle_info/2","doc":"","ref":"gen_changes.html#handle_info/2"},{"type":"function","title":"gen_changes.init/1","doc":"","ref":"gen_changes.html#init/1"},{"type":"function","title":"gen_changes.start_link/4","doc":"create a gen_changes process as part of a supervision tree. The function should be called, directly or indirectly, by the supervisor. InitArgs::list()) -> term() changesoptions() = [changeoption()] changeoption() = {include_docs, string()} | {filter, string()} | {since, integer()|string()} | {heartbeat, string()|boolean()}","ref":"gen_changes.html#start_link/4"},{"type":"function","title":"gen_changes.stop/1","doc":"","ref":"gen_changes.html#stop/1"},{"type":"function","title":"gen_changes.terminate/2","doc":"","ref":"gen_changes.html#terminate/2"},{"type":"module","title":"json_stream_parse","doc":"","ref":"json_stream_parse.html"},{"type":"function","title":"json_stream_parse.feed/2","doc":"","ref":"json_stream_parse.html#feed/2"},{"type":"function","title":"json_stream_parse.finish/1","doc":"","ref":"json_stream_parse.html#finish/1"},{"type":"function","title":"json_stream_parse.init/0","doc":"","ref":"json_stream_parse.html#init/0"},{"type":"extras","title":"Readme","doc":"# Couchbeam - simple Apache CouchDB client library for Erlang applications #\n\nCopyright (c) 2009-2025 Benoit Chesneau.\n\n__Version:__ 1.7.1\n\n# couchbeam\n\nCouchbeam is a simple erlang library for [Barrel](https://barrel-db.org) or [Apache CouchDB](http://couchdb.apache.org). Couchbeam provides you a full featured and easy client to access and manage multiple nodes.\n\n#### Main features:\n\n- Complete support of the BarrelDB and Apache CouchDB API\n- Stream view results to your app\n- Stream changes feeds\n- reduced memory usage\n- fetch and send attachments in a streaming fashion\n- JSON encoding/decoding via Erlang/OTP stdlib `json` with maps\n\n#### Useful modules are:\n\n- [`couchbeam`](http://github.com/benoitc/couchbeam/blob/master/doc/couchbeam.md): The `couchbeam` module is the main interface for interaction with this application. It includes functions for managing connections to Apache CouchDB or RCOUCH servers and databases and for performing document creations, updates, deletes, views...\n- [`couchbeam_doc`](http://github.com/benoitc/couchbeam/blob/master/doc/couchbeam_doc.md) Module to manipulate Documents structures. You can set values,\nupdates keys, ...\n- [`couchbeam_attachments`](http://github.com/benoitc/couchbeam/blob/master/doc/couchbeam_attachments.md): Module to manipulate attachments. You can add, remove\nattachments in a Document structure (inline attachments).\n- [`couchbeam_view`](http://github.com/benoitc/couchbeam/blob/master/doc/couchbeam_view.md): Module to manage view results.\n- [`couchbeam_changes`](http://github.com/benoitc/couchbeam/blob/master/doc/couchbeam_changes.md): Module to manage changes feeds. Follow continuously\nthe changes in a db or get all changes at once.\n\nThe goal of Couchbeam is to ease the access to the Apache CouchDB and RCOUCH HTTP API in erlang.\n\nRead the [NEWS](https://raw.github.com/benoitc/couchbeam/master/NEWS) file\nto get last changelog.","ref":"readme.html"},{"type":"extras","title":"Installation - Readme","doc":"Download the sources from our [Github repository](http://github.com/benoitc/couchbeam)\n\nTo build the application simply run 'make'. This should build .beam, .app\nfiles and documentation.\n\nTo run tests run 'make test'.\nTo generate doc, run 'make doc'.\n\nOr add it to your rebar config\n\n```\n erlang\n{deps, [\n ....\n {couchbeam, \".*\", {git, \"git://github.com/benoitc/couchbeam.git\", {branch, \"master\"}}}\n]}.\n```\n\nNote to compile with jiffy you need to define in the erlang options the\nvariable `WITH_JIFFY`.\n\nif you use rebar, add to your `rebar.config`:\n\n```\n erlang\n{erl_opts, [{d, 'WITH_JIFFY'}]}.\n```\n\nor use the `rebar` command with the `-D` options:\n\n```\n sh\nrebar compile -DWITH_JIFFY\n```","ref":"readme.html#installation"},{"type":"extras","title":"Basic Usage - Readme","doc":"","ref":"readme.html#basic-usage"},{"type":"extras","title":"Start couchbeam - Readme","doc":"Couchbeam is an [OTP](http://www.erlang.org/doc/design_principles/users_guide.html)\napplication. You have to start it first before using any of the\nfunctions. The couchbeam application will start the default socket pool\nfor you.\n\nTo start in the console run:\n\n```\n sh\n$ erl -pa ebin\n1> couchbeam:start().\nok\n```\n\nIt will start hackney and all of the application it depends on:\n\n```\n erlang\napplication:start(crypto),\napplication:start(asn1),\napplication:start(public_key),\napplication:start(ssl),\napplication:start(hackney),\napplication:start(couchbeam).\n```\n\nOr add couchbeam to the applications property of your .app in a release","ref":"readme.html#start-couchbeam"},{"type":"extras","title":"Create a connection to the server - Readme","doc":"To create a connection to a server machine:\n\n```\n erlang\nUrl = \"http://localhost:5984\",\nOptions = [],\nS = couchbeam:server_connection(Url, Options).\n```\n\nTest the connection with `couchbeam:server_info/1` :\n\n```\n erlang\n{ok, _Version} = couchbeam:server_info(S).\n```","ref":"readme.html#create-a-connection-to-the-server"},{"type":"extras","title":"Open or Create a database - Readme","doc":"All document operations are done in databases. To open a database simply do:\n\n```\n erlang\nOptions = [],\n{ok, Db} = couchbeam:open_db(Server, \"testdb\", Options).\n```\n\nTo create a new one:\n\n```\n erlang\nOptions = [],\n{ok, Db} = couchbeam:create_db(Server, \"testdb\", Options).\n```\n\nYou can also use the shorcut `couchbeam:open_or_create_db/3`. that\nwill create a database if it does not exist.","ref":"readme.html#open-or-create-a-database"},{"type":"extras","title":"Make a new document - Readme","doc":"Make a new document:\n\n```\n erlang\nDoc = #{\n <<\"_id\">> => <<\"test\">>,\n <<\"content\">> => <<\"some text\">>\n}.\n```\n\nAnd save it to the database:\n\n```\n erlang\n{ok, Doc1} = couchbeam:save_doc(Db, Doc).\n```\n\nThe `couchbeam:save_doc/2` return a new document with updated\nrevision and if you do not specify the _id, a unique document id.\n\nTo change an document property use functions from `couchbeam_doc`.","ref":"readme.html#make-a-new-document"},{"type":"extras","title":"Retrieve a document - Readme","doc":"To retrieve a document do:\n\n```\n erlang\n{ok, Doc2} = couchbeam:open_doc(Db, \"test\").\n```\n\nIf you want a specific revision:\n\n```\n erlang\nRev = couchbeam_doc:get_rev(Doc1),\nOptions = [{rev, Rev}],\n{ok, Doc3} = couchbeam:open_doc(Db, \"test\", Options).\n```\n\nHere we get the revision from the document we previously stored. Any\noptions from the Apache CouchDB and RCOUCH API can be used.","ref":"readme.html#retrieve-a-document"},{"type":"extras","title":"Get all documents - Readme","doc":"To get all documents you have first to create an object\nthat will keep all informations.\n\n```\n erlang\nOptions = [include_docs],\n{ok, AllDocs} = couchbeam_view:all(Db, Options).\n```\n\nExample result (abridged):\n\n```\n erlang\n{ok, [\n #{\n <<\"id\">> => <<\"7a0ce91d0d0c5e5b51e904d1ee3266a3\">>,\n <<\"key\">> => <<\"7a0ce91d0d0c5e5b51e904d1ee3266a3\">>,\n <<\"value\">> => #{<<\"rev\">> => <<\"15-15c0b3c4efa74f9a80d28ac040f18bdb\">>},\n <<\"doc\">> => #{\n <<\"_id\">> => <<\"7a0ce91d0d0c5e5b51e904d1ee3266a3\">>,\n <<\"_rev\">> => <<\"15-15c0b3c4efa74f9a80d28ac040f18\"...>>\n }\n }\n]}.\n```\n\nAll functions to manipulate these results are in the `couchbeam_view` module.","ref":"readme.html#get-all-documents"},{"type":"extras","title":"Couch DB views - Readme","doc":"Views are workin like all_docs. You have to create a View object before\ndoing anything.\n\n```\n erlang\nOptions = [],\nDesignName = \"designname\",\nViewName = \"viewname\",\n{ok, ViewResults} = couchbeam_view:fetch(Db, {DesignName, ViewName}, Options).\n```\n\nLike the `all_docs` function, use the functions\nfrom `couchbeam_view` module to manipulate results. You can pass\nany querying options from the [view API](http://docs.rcouch.org/en/latest/api/ddoc/views.html).\n\nDesign doc are created like any documents:\n\n```\n erlang\nDesignDoc = #{\n <<\"_id\">> => <<\"_design/couchbeam\">>,\n <<\"language\">> => <<\"javascript\">>,\n <<\"views\">> => #{\n <<\"test\">> => #{\n <<\"map\">> => <<\"function (doc) {\\n if (doc.type == \\\"test\\\") {\\n emit(doc._id, doc);\\n}\\n}\">>\n },\n <<\"test2\">> => #{\n <<\"map\">> => <<\"function (doc) {\\n if (doc.type == \\\"test2\\\") {\\n emit(doc._id, null);\\n}\\n}\">>\n }\n }\n},\n{ok, DesignDoc1} = couchbeam:save_doc(Db, DesignDoc).\n```\n\nYou can also use [couchapp](http://github.com/couchapp/couchapp) to manage them\nmore easily.","ref":"readme.html#couch-db-views"},{"type":"extras","title":"Stream View results - Readme","doc":"While you can get results using `couchbeam_views:fetch/2`, you can also retrieve\nall rows in a streaming fashion:\n\n```\n erlang\nViewFun = fun(Ref, F) ->\n receive\n {Ref, done} ->\n io:format(\"done\", []),\n done;\n {Ref, {row, Row}} ->\n io:format(\"got ~p~n\", [Row]),\n F(Ref, F);\n {error, Ref, Error} ->\n io:format(\"error: ~p~n\", [Error])\n end\nend,\n\n{ok, StreamRef} = couchbeam_view:stream(Db, 'all_docs'),\nViewFun(StreamRef, ViewFun),\n{ok, StreamRef2} = couchbeam_view:stream(Db, 'all_docs', [include_docs]),\nViewFun(StreamRef2, ViewFun).\n```\n\nYou can of course do the same with a view:\n\n```\n erlang\nDesignNam = \"designname\",\nViewName = \"viewname\",\n{ok, StreamRef3} = couchbeam_view:stream(Db, {DesignNam, ViewName}, [include_docs]),\nViewFun(StreamRef3, ViewFun).\n```","ref":"readme.html#stream-view-results"},{"type":"extras","title":"Put, Fetch and Delete documents attachments - Readme","doc":"You can add attachments to any documents. Attachments could be anything.\n\nTo send an attachment:\n\n```\n erlang\nDocID = \"test\",\nAttName = \"test.txt\",\nAtt = \"some content I want to attach\",\nOptions = []\n{ok, _Result} = couchbeam:put_attachment(Db, DocId, AttName, Att, Options).\n```\n\nAll attachments are streamed to servers. `Att` could be also be an iolist\nor functions, see `couchbeam:put_attachment/5` for more information.\n\nTo fetch an attachment:\n\n```\n erlang\n{ok Att1} = couchbeam:fetch_attachment(Db, DocId, AttName).\n```\n\nYou can use `couchbeam:stream_attachment/1` for the stream\nfetch.\n\nTo delete an attachment:\n\n```\n erlang\n{ok, Doc4} = couchbeam:open_doc(Db, DocID),\nok = couchbeam:delete_attachment(Db, Doc4, AttName).\n```","ref":"readme.html#put-fetch-and-delete-documents-attachments"},{"type":"extras","title":"Changes - Readme","doc":"Apache CouchDB and RCOUCH provide a means to get a list of changes made to documents in\nthe database. With couchbeam you can get changes using `couchbeam_changes:follow_once/2`.\nThis function returns all changes immediately. But you can also retrieve\nall changes rows using longpolling :\n\n```\n erlang\nOptions = [],\n{ok, LastSeq, Rows} = couchbeam_changes:follow_once(Db, Options).\n```\n\nOptions can be any Changes query parameters. See the [change API](http://docs.rcouch.org/en/latest/api/database/changes.html) for more informations.\n\nYou can also get [continuous](http://docs.rcouch.org/en/latest/api/database/changes.html#continuous):\n\n```\n erlang\nChangesFun = fun(StreamRef, F) ->\n receive\n {StreamRef, {done, LastSeq}} ->\n io:format(\"stopped, last seq is ~p~n\", [LastSeq]),\n ok;\n {StreamRef, {change, Change}} ->\n io:format(\"change row ~p ~n\", [Change]),\n F(StreamRef, F);\n {StreamRef, Error}->\n io:format(\"error ? ~p ~n,\", [Error])\n end\nend,\nOptions = [continuous, heartbeat],\n{ok, StreamRef} = couchbeam_changes:follow(Db, Options),\nChangesFun(StreamRef, ChangesFun).\n```\n\n> **Note**: a `gen_changes` behaviour exists in couchbeam that you can\nuse to create your own specific gen_server receiving changes. Have a\nlook in the\n[example](https://github.com/benoitc/couchbeam/blob/master/examples/test_gen_changes.erl)\nfor more info.","ref":"readme.html#changes"},{"type":"extras","title":"Authentication/ Connections options - Readme","doc":"You can authenticate to the database or Apache CouchDB or RCOUCH server by filling\noptions to the Option list in `couchbeam:server_connection/4` for the\nserver or in `couchbeam:create_db/3`, `couchbeam:open_db/3`,\n`couchbeam:open_or_create_db/3` functions.\n\nTo set basic_auth on a server:\n\n```\n erlang\nUserName = \"guest\",\nPassword = \"test\",\nUrl = \"http://localhost:5984\",\nOptions = [{basic_auth, {UserName, Password}}],\nS1 = couchbeam:server_connection(Url, Options).\n```\n\nCouchbeam support SSL, OAuth, Basic Authentication, and Proxy. You can\nalso set a cookie. For more informations about the options have a look\nin the `couchbeam:server_connection/2` documentation.","ref":"readme.html#authentication-connections-options"},{"type":"extras","title":"Contribute - Readme","doc":"For issues, comments or feedback please [create an\nissue](http://github.com/benoitc/couchbeam/issues).","ref":"readme.html#contribute"},{"type":"extras","title":"Changelog","doc":"couchbeam NEWS\n--------------\n\nversion 2.0.0 / 2025-09-03\n--------------------------\n\n- move from propos lists to maps for json\n- remove JSX & Jiffy Usage for erlang/0TP 28.0+ json module\n- View and changes streaming now use a simpler parser\n\n** BREAKING CHANGE **\n\n- move to maps, you will need to migrate your application to use them. \nno backward compatibility is provided\n\nversion 1.7.1 / 2025-07-24\n---------------------------\n\n- update hackney depdendency to 1.25.0\n\nversion 1.7.0 / 2025-05-28\n--------------------------\n\n- fix resource leaks and race conditions in stream modules\n- fix unclosed hackney connections on error paths\n- add proper cleanup for monitor references using try-finally\n- fix ETS table race conditions by checking process liveness\n- improve stream initialization order to prevent races\n- add error handling for hackney operations to prevent leaks\n- fix changes stream registration race condition by registering before parent notification\n\nversion 1.6.0 / 2025-01-26\n--------------------------\n\n- add support for CouchDB _find endpoint\n- add ability to query _show functions \n- add option for disabling view_stream usage (enabled by default)\n- fix error handling in gen_changes callback handling\n- fix resource cleanup in stream modules to prevent connection leaks\n- improve replication test reliability and timeout handling\n- update hackney dependency to 1.23\n- update jsx dependency\n- add GitHub Actions for CouchDB testing\n- fix dialyzer complaints and pattern matching issues\n- OTP 27 compatibility improvements\n\nversion 1.5.4 / 2025-02-20\n--------------------------\n\n- bump hackney 1.22.0\n\nversion 1.5.3 / 2024-08-20\n--------------------------\n\n- fix packaging\n\nversion 1.5.1 / 2024-11-07\n--------------------------\n\n- fix pattern matching\n\nversion 1.5.1 / 2024-11-07\n--------------------------\n\n- fix: handle condition that may cause persistent CLOSE-WAIT sockets\n\nversion 1.5.0 / 2023-10-11\n--------------------------\n\n- use hackney 1.20.0\n- fix compatibility with couchdb 3\n- fix compatibility with Erlang >= 23\n\nversion 1.4.1 / 2016-09-26\n--------------------------\n\n- maintainance update\n\nversion 1.4.0 / 2016-09-22\n--------------------------\n\n- maintainance update.\n\nversion 1.3.1 / 2016-07-01\n--------------------------\n\n- fix: accept 202 status in `couchbeam:save_doc/4` function (#144)\n- fix: spec syntax to build with Erlang 19 (#145)\n\nversion 1.3.0 / 2016-03-22\n--------------------------\n\n- add `couchbeam:all_dbs/2`\n- add `couchbeam:view_cleanup/1`\n- add `couchbeam:design_info/2`\n- add `post_decode` function to view stream\n- add Elixir mix support\n- fix: handle http errors in view stream (#140)\n- fix: build with latest rebar3\n\nversion 1.2.1 / 2015/11/04\n--------------------------\n\n- also support hackney 1.4.4 for rebar2.\n- fix hex.pm release to really use 1.4.4\n\nversion 1.2.0 / 2015/11/04\n--------------------------\n\n- move to eunit for tests.\n- hex.pm support\n- mix & rebar3 build tools support\n- bump hackney to 1.4.4\n- bump jsx to 2.2.8","ref":"news.html"},{"type":"extras","title":"Breaking change - Changelog","doc":"erlang-oauth is now optionnal and won't be installed by default.\n\nversion 1.1.8 / 2015-08-27\n--------------------------\n\n- use latest stable branch of [hackney](https://github.com/benoitc/hackney)\n\nversion 1.1.7 / 2015-03-11\n--------------------------\n\n- bump [hackney](https://github.com/benoitc/hackney) to 1.1.0\n- fix `Conten-Type` header ehen posting doc IDS in changes #126\n- fix documentation\n\nversion 1.1.6 / 2015-01-02\n--------------------------\n\n- fix `included_applications` (#122)\n\nversion 1.1.5 / 2014-12-09\n--------------------------\n\n- improvement: do not force connections options to nodelay\n- update to [Hackney](https://github.com/benoitc/hackney) 1.0.4 fix #120\n- fix: retry fecthing UUIDS on error (#121)\n\nversion 1.1.4 / 2014-12-01\n--------------------------\n\n- update to [Hackney](https://github.com/benoitc/hackney) 1.0.1: more SSL\n certificate authority handling.\n- fix: changes stream\n\nversion 1.1.3 / 2014-11-30\n--------------------------\n\n- update to [Hackney](https://github.com/benoitc/hackney) 1.0.0\n\nversion 1.1.2 / 2014-11-15\n--------------------------\n\n- remove spurious prints\n\nversion 1.1.1 / 2014-11-11\n--------------------------\n\n- update to [hackney 0.15.0](https://github.com/benoitc/hackney/releases ),\n improving performances and concurrency\n- fix `couchbeam:doc_exists/2`(#116)\n- fix `couchbeam:reply_att/1` (#114)\n\n\nversion 1.1.0 / 2014-10-28\n--------------------------\n\n- update to [hackney 0.14.3](https://github.com/benoitc/hackney/releases)\n- fix memory leaks\n- correctly close sockets\n- fix streaming issue: don't wait the stream timeout to report the initial\n error.\n- update JSX dependency to version 2.1.1\n\nversion 1.0.7 / 2014-07-08\n--------------------------\n\n- bump to [hackney 0.13.0](https://github.com/benoitc/hackney/releases/tag/0.13.0)\n\nversion 1.0.6 / 2014-04-18\n--------------------------\n\n- bump to [hackney 0.12.1](https://github.com/benoitc/hackney/releases/tag/0.12.2)\n\n\nversion 1.0.5 / 2014-04-18\n--------------------------\n\n- improve connections with HTTP proxies\n- improve content-types detection of attachments\n- improve URL encoding normalzation, useful when connecting to an\n international domain/URI\n- URL resolving is faster\n- bump to [hackney 0.12.0](https://github.com/benoitc/hackney/releases/tag/0.12.0)\n\nversion 1.0.4 / 2014-04-15\n--------------------------\n\n- remove spurious print\n\nversion 1.0.3 / 2014-04-15\n--------------------------\n\n- add support for the `new_edits` option in bulk doc API.\n- improvement: send a doc as multipart that already contains attachments\n- bump [hackney](http://github.com/benoitc/hackney) to 0.11.2\n- fix path encoding\n\nversion 1.0.2 / 2014-01-03\n--------------------------\n\n- fix: send a doc as multipart that already contains attachments\n\n\nversion 1.0.1 / 2013-12-30\n--------------------------\n\n- fix connection reusing in changes and view streams\n- bump hackney version to 0.10.1\n\n\nversion 1.0.0 / 2013-12-21\n--------------------------\n\n**First stable release**. This is a supported release.\n\n- send a doc and its attachments efficiently using the [multipart\n API](http://docs.couchdb.org/en/latest/api/document/common.html#creating-multiple-attachments).\n- add `couchbeam:get_config/{1,2,3}`, `couchbeam:set_config/{4,5}` and\n `couchbeam:delete_config/{3,4}` to use the [config\nAPI](http://docs.couchdb.org/en/latest/api/server/configuration.html).\n- add `couchbeam_uuids:random/0` and `couchbeam_uuids:utc_random/0` to\n generate UUIDS in your app instead of reusing the UUID generated on\nthe node. By default couchbeam is fetching from the node, which is\n- add `{error, forbidden}` and `{error, unauthenticated}` as possible\n results of a reply.\nbetter if you want to use UUID based on the node time.\n- fix accept header handling\n\n\nversion 0.10.0 / 2013-12-21\n---------------------------\n\n- add `couchbeam:copy_doc/{2,3}` to support the COPY API\n- add `couchbeam:get_missing_revs/2` to get the list of missing\n revisions\n- add support of the [multipart\n API](http://docs.couchdb.org/en/latest/api/document/common.html#efficient-multiple-attachments-retrieving) when fetching a doc: This change make\n `couchbeam:open_doc/3` returns a multipart response `{ok, {multipart, Stream}}`\n when using the `attachments=true` option. A new option `{accept, <<\"multipart/mixed\">>}`\n can also be used with the options `open_revs` or `revs` to fetch the response as a multipart.\n- bump the [hackney](http://github.com/benoitc/hackney) version to\n **0.9.1** .\n\n\nWith this change you can now efficiently retrieve a doc with all of its\nattachments or a doc wit all its revisions.\n master\n\nversion 0.9.3 / 2013-12-07\n--------------------------\n\n- fix: couchbeam:open_or_create_db/2\n\nversion 0.9.2 / 2013-12-07\n--------------------------\n\n- bump hackney version to 0.8.3\n\nversion 0.9.1 / 2013-12-05\n--------------------------\n\n- fix design docid encoding\n\nversion 0.9.0 / 2013-12-05\n--------------------------\n\nThis is a major release pre-1.0. API is now frozen and won't change much\nuntil the version 1.0.\n\n- replaced the use of ibrowse by hackney to handle HTTP connections\n- new [streaming\n API](https://github.com/benoitc/couchbeam#stream-view-results) in view\n- breaking change: remobe\n- breaking change: remove deprecated view API. Everything is now managed in the\n [couch_view](https://github.com/benoitc/couchbeam/blob/master/doc/couchbeam_view.md) module.\n- replace 'couchbeam_changes:stream' and 'couchbeam_changes:fetch'\n functions by 'couchbeam_changes/follow' and 'couchbeam_changes:follow_once'.\n- breaking change: new attachment API\n- new: JSX a pure erlang JSON encoder/decoder is now the default. Jiffy\n can be set at the compilation by defining 'WITH_JIFFY' in the Erlang\noptions.\n- removed mochiweb dependency.\n\n\nversion 0.7.0 / 2011-07-05\n--------------------------\n\nThis release contains backwards incompatible changes.\n\n- New and more efficient couchbeam_changes API, we now parse json stream\n instead of the try catch steps we used before.\n- New and more efficient couchbeam_view API. we now parse json stream\n instead of getting all results. New couchbeam_view:stream and\ncouchbeam_view fetch functions have been added. We also don't use any\nmore a view record in other functions\n- HTTP functions have been moved to couchbeam_httpc modules\n- gen_changes behaviour has been updated to use the couchbeam_changes\n API. It's also abble to restart a lost connection for longpoll and\ncontinuous feeds.\n\nBreaking Changes:\n\n- couchbeam:view and couchbeam:all_docs have been deprecated. Old views\n functions using the #view{} record from these functions have been\nmoved in couchbeam_oldview module.\n- couchbeam:wait_changes, couchbeam:wait_changes_once, couchbeam:changes\n functions have been deprecated and are now replaced by\ncouchbeam_changes:stream and couchbeam_changes:fetch functions.","ref":"news.html#breaking-change"},{"type":"extras","title":"Notice","doc":"Couchbeam\n---------\n\n2009-2025 (c) Benoit Chesneau\n\ncouchbeam is released under the MIT license. See the LICENSE file for the\ncomplete license.","ref":"notice.html"},{"type":"extras","title":"License","doc":"2009-2025 (c) Benoit Chesneau\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.","ref":"license.html"}],"proglang":"erlang","content_type":"text/markdown","producer":{"name":"ex_doc","version":"0.38.2"}} \ No newline at end of file diff --git a/site/dist/sidebar_items-A03F7C15.js b/site/dist/sidebar_items-A03F7C15.js deleted file mode 100644 index 41e74657..00000000 --- a/site/dist/sidebar_items-A03F7C15.js +++ /dev/null @@ -1 +0,0 @@ -sidebarNodes={"modules":[{"id":"couchbeam","deprecated":false,"group":"","title":"couchbeam","sections":[],"nodeGroups":[{"name":"Types","nodes":[{"id":"db/0","deprecated":false,"title":"db/0","anchor":"t:db/0"},{"id":"doc/0","deprecated":false,"title":"doc/0","anchor":"t:doc/0"},{"id":"doc_stream/0","deprecated":false,"title":"doc_stream/0","anchor":"t:doc_stream/0"},{"id":"ejson_object/0","deprecated":false,"title":"ejson_object/0","anchor":"t:ejson_object/0"},{"id":"mp_attachment/0","deprecated":false,"title":"mp_attachment/0","anchor":"t:mp_attachment/0"},{"id":"mp_attachments/0","deprecated":false,"title":"mp_attachments/0","anchor":"t:mp_attachments/0"},{"id":"server/0","deprecated":false,"title":"server/0","anchor":"t:server/0"}],"key":"types"},{"name":"Functions","nodes":[{"id":"all_dbs/1","deprecated":false,"title":"all_dbs(Server)","anchor":"all_dbs/1"},{"id":"all_dbs/2","deprecated":false,"title":"all_dbs(Server, Options)","anchor":"all_dbs/2"},{"id":"compact/1","deprecated":false,"title":"compact(Db)","anchor":"compact/1"},{"id":"compact/2","deprecated":false,"title":"compact(Db, DesignName)","anchor":"compact/2"},{"id":"copy_doc/2","deprecated":false,"title":"copy_doc(Db, Doc)","anchor":"copy_doc/2"},{"id":"copy_doc/3","deprecated":false,"title":"copy_doc(Db, Doc, Dest)","anchor":"copy_doc/3"},{"id":"create_db/2","deprecated":false,"title":"create_db(Server, DbName)","anchor":"create_db/2"},{"id":"create_db/3","deprecated":false,"title":"create_db(Server, DbName, Options)","anchor":"create_db/3"},{"id":"create_db/4","deprecated":false,"title":"create_db(Server, DbName0, Options, Params)","anchor":"create_db/4"},{"id":"db_exists/2","deprecated":false,"title":"db_exists(Server, DbName)","anchor":"db_exists/2"},{"id":"db_info/1","deprecated":false,"title":"db_info(Db)","anchor":"db_info/1"},{"id":"delete_attachment/3","deprecated":false,"title":"delete_attachment(Db, Doc, Name)","anchor":"delete_attachment/3"},{"id":"delete_attachment/4","deprecated":false,"title":"delete_attachment(Db, DocOrDocId, Name, Options)","anchor":"delete_attachment/4"},{"id":"delete_db/1","deprecated":false,"title":"delete_db(Db)","anchor":"delete_db/1"},{"id":"delete_db/2","deprecated":false,"title":"delete_db(Server, DbName)","anchor":"delete_db/2"},{"id":"delete_doc/2","deprecated":false,"title":"delete_doc(Db, Doc)","anchor":"delete_doc/2"},{"id":"delete_doc/3","deprecated":false,"title":"delete_doc(Db, Doc, Options)","anchor":"delete_doc/3"},{"id":"delete_docs/2","deprecated":false,"title":"delete_docs(Db, Docs)","anchor":"delete_docs/2"},{"id":"delete_docs/3","deprecated":false,"title":"delete_docs(Db, Docs, Options)","anchor":"delete_docs/3"},{"id":"design_info/2","deprecated":false,"title":"design_info(Db, DesignName)","anchor":"design_info/2"},{"id":"doc_exists/2","deprecated":false,"title":"doc_exists(Db, DocId)","anchor":"doc_exists/2"},{"id":"end_doc_stream/1","deprecated":false,"title":"end_doc_stream(_)","anchor":"end_doc_stream/1"},{"id":"ensure_full_commit/1","deprecated":false,"title":"ensure_full_commit(Db)","anchor":"ensure_full_commit/1"},{"id":"ensure_full_commit/2","deprecated":false,"title":"ensure_full_commit(Db, Options)","anchor":"ensure_full_commit/2"},{"id":"fetch_attachment/3","deprecated":false,"title":"fetch_attachment(Db, DocId, Name)","anchor":"fetch_attachment/3"},{"id":"fetch_attachment/4","deprecated":false,"title":"fetch_attachment(Db, DocId, Name, Options0)","anchor":"fetch_attachment/4"},{"id":"find/3","deprecated":false,"title":"find(Db, Selector, Params)","anchor":"find/3"},{"id":"get_missing_revs/2","deprecated":false,"title":"get_missing_revs(Db, IdRevs)","anchor":"get_missing_revs/2"},{"id":"get_uuid/1","deprecated":false,"title":"get_uuid(Server)","anchor":"get_uuid/1"},{"id":"get_uuids/2","deprecated":false,"title":"get_uuids(Server, Count)","anchor":"get_uuids/2"},{"id":"lookup_doc_rev/2","deprecated":false,"title":"lookup_doc_rev(Db, DocId)","anchor":"lookup_doc_rev/2"},{"id":"lookup_doc_rev/3","deprecated":false,"title":"lookup_doc_rev(Db, DocId, Params)","anchor":"lookup_doc_rev/3"},{"id":"open_db/2","deprecated":false,"title":"open_db(Server, DbName)","anchor":"open_db/2"},{"id":"open_db/3","deprecated":false,"title":"open_db(Server, DbName, Options)","anchor":"open_db/3"},{"id":"open_doc/2","deprecated":false,"title":"open_doc(Db, DocId)","anchor":"open_doc/2"},{"id":"open_doc/3","deprecated":false,"title":"open_doc(Db, DocId, Params)","anchor":"open_doc/3"},{"id":"open_or_create_db/2","deprecated":false,"title":"open_or_create_db(Server, DbName)","anchor":"open_or_create_db/2"},{"id":"open_or_create_db/3","deprecated":false,"title":"open_or_create_db(Server, DbName, Options)","anchor":"open_or_create_db/3"},{"id":"open_or_create_db/4","deprecated":false,"title":"open_or_create_db(Server, DbName0, Options, Params)","anchor":"open_or_create_db/4"},{"id":"put_attachment/4","deprecated":false,"title":"put_attachment(Db, DocId, Name, Body)","anchor":"put_attachment/4"},{"id":"put_attachment/5","deprecated":false,"title":"put_attachment(Db, DocId, Name, Body, Options)","anchor":"put_attachment/5"},{"id":"replicate/2","deprecated":false,"title":"replicate(Server, RepObj)","anchor":"replicate/2"},{"id":"replicate/3","deprecated":false,"title":"replicate(Server, Source, Target)","anchor":"replicate/3"},{"id":"replicate/4","deprecated":false,"title":"replicate(Server, Source, Target, Options)","anchor":"replicate/4"},{"id":"save_doc/2","deprecated":false,"title":"save_doc(Db, Doc)","anchor":"save_doc/2"},{"id":"save_doc/3","deprecated":false,"title":"save_doc(Db, Doc, Options)","anchor":"save_doc/3"},{"id":"save_doc/4","deprecated":false,"title":"save_doc(Db, MapDoc, Atts, Options)","anchor":"save_doc/4"},{"id":"save_docs/2","deprecated":false,"title":"save_docs(Db, Docs)","anchor":"save_docs/2"},{"id":"save_docs/3","deprecated":false,"title":"save_docs(Db, Docs, Options)","anchor":"save_docs/3"},{"id":"send_attachment/2","deprecated":false,"title":"send_attachment(Ref, Msg)","anchor":"send_attachment/2"},{"id":"server_connection/0","deprecated":false,"title":"server_connection()","anchor":"server_connection/0"},{"id":"server_connection/1","deprecated":false,"title":"server_connection(URL)","anchor":"server_connection/1"},{"id":"server_connection/2","deprecated":false,"title":"server_connection(URL, Options0)","anchor":"server_connection/2"},{"id":"server_connection/4","deprecated":false,"title":"server_connection(Host, Port, Prefix, OptionsList)","anchor":"server_connection/4"},{"id":"server_info/1","deprecated":false,"title":"server_info(Server)","anchor":"server_info/1"},{"id":"stream_attachment/1","deprecated":false,"title":"stream_attachment(Ref)","anchor":"stream_attachment/1"},{"id":"stream_doc/1","deprecated":false,"title":"stream_doc(_)","anchor":"stream_doc/1"},{"id":"view_cleanup/1","deprecated":false,"title":"view_cleanup(Db)","anchor":"view_cleanup/1"}],"key":"functions"}]},{"id":"couchbeam_app","deprecated":false,"group":"","title":"couchbeam_app","sections":[],"nodeGroups":[{"name":"Functions","nodes":[{"id":"start/2","deprecated":false,"title":"start(Type, StartArgs)","anchor":"start/2"},{"id":"stop/1","deprecated":false,"title":"stop(State)","anchor":"stop/1"}],"key":"functions"}]},{"id":"couchbeam_attachments","deprecated":false,"group":"","title":"couchbeam_attachments","sections":[],"nodeGroups":[{"name":"Types","nodes":[{"id":"doc/0","deprecated":false,"title":"doc/0","anchor":"t:doc/0"},{"id":"ejson_object/0","deprecated":false,"title":"ejson_object/0","anchor":"t:ejson_object/0"}],"key":"types"},{"name":"Functions","nodes":[{"id":"add_inline/3","deprecated":false,"title":"add_inline(Doc, Content, AName)","anchor":"add_inline/3"},{"id":"add_inline/4","deprecated":false,"title":"add_inline(Doc, Content, AName, ContentType)","anchor":"add_inline/4"},{"id":"add_stub/3","deprecated":false,"title":"add_stub(Doc, Name, ContentType)","anchor":"add_stub/3"},{"id":"delete_inline/2","deprecated":false,"title":"delete_inline(Doc, AName)","anchor":"delete_inline/2"}],"key":"functions"}]},{"id":"couchbeam_changes","deprecated":false,"group":"","title":"couchbeam_changes","sections":[],"nodeGroups":[{"name":"Types","nodes":[{"id":"changes_option/0","deprecated":false,"title":"changes_option/0","anchor":"t:changes_option/0"},{"id":"changes_options/0","deprecated":false,"title":"changes_options/0","anchor":"t:changes_options/0"},{"id":"db/0","deprecated":false,"title":"db/0","anchor":"t:db/0"},{"id":"server/0","deprecated":false,"title":"server/0","anchor":"t:server/0"}],"key":"types"},{"name":"Functions","nodes":[{"id":"cancel_stream/1","deprecated":false,"title":"cancel_stream(Ref)","anchor":"cancel_stream/1"},{"id":"follow/1","deprecated":false,"title":"follow(Db)","anchor":"follow/1"},{"id":"follow/2","deprecated":false,"title":"follow(Db, Options)","anchor":"follow/2"},{"id":"follow_once/1","deprecated":false,"title":"follow_once(Db)","anchor":"follow_once/1"},{"id":"follow_once/2","deprecated":false,"title":"follow_once(Db, Options)","anchor":"follow_once/2"},{"id":"stream_next/1","deprecated":false,"title":"stream_next(Ref)","anchor":"stream_next/1"}],"key":"functions"}]},{"id":"couchbeam_changes_stream","deprecated":false,"group":"","title":"couchbeam_changes_stream","sections":[],"nodeGroups":[{"name":"Functions","nodes":[{"id":"init_stream/5","deprecated":false,"title":"init_stream(Parent, Owner, StreamRef, Db, Options)","anchor":"init_stream/5"},{"id":"maybe_continue/1","deprecated":false,"title":"maybe_continue(State)","anchor":"maybe_continue/1"},{"id":"start_link/4","deprecated":false,"title":"start_link(Owner, StreamRef, Db, Options)","anchor":"start_link/4"},{"id":"system_code_change/4","deprecated":false,"title":"system_code_change(Misc, _, _, _)","anchor":"system_code_change/4"},{"id":"system_continue/3","deprecated":false,"title":"system_continue(_, _, _)","anchor":"system_continue/3"},{"id":"system_terminate/4","deprecated":false,"title":"system_terminate(Reason, _, _, State)","anchor":"system_terminate/4"},{"id":"wait_reconnect/1","deprecated":false,"title":"wait_reconnect(State)","anchor":"wait_reconnect/1"}],"key":"functions"}]},{"id":"couchbeam_changes_sup","deprecated":false,"group":"","title":"couchbeam_changes_sup","sections":[],"nodeGroups":[{"name":"Functions","nodes":[{"id":"init/1","deprecated":false,"title":"init(_)","anchor":"init/1"},{"id":"start_link/0","deprecated":false,"title":"start_link()","anchor":"start_link/0"}],"key":"functions"}]},{"id":"couchbeam_doc","deprecated":false,"group":"","title":"couchbeam_doc","sections":[],"nodeGroups":[{"name":"Types","nodes":[{"id":"doc/0","deprecated":false,"title":"doc/0","anchor":"t:doc/0"},{"id":"ejson_array/0","deprecated":false,"title":"ejson_array/0","anchor":"t:ejson_array/0"},{"id":"ejson_number/0","deprecated":false,"title":"ejson_number/0","anchor":"t:ejson_number/0"},{"id":"ejson_object/0","deprecated":false,"title":"ejson_object/0","anchor":"t:ejson_object/0"},{"id":"ejson_string/0","deprecated":false,"title":"ejson_string/0","anchor":"t:ejson_string/0"},{"id":"ejson_term/0","deprecated":false,"title":"ejson_term/0","anchor":"t:ejson_term/0"}],"key":"types"},{"name":"Functions","nodes":[{"id":"delete_value/2","deprecated":false,"title":"delete_value(Key, JsonObj)","anchor":"delete_value/2"},{"id":"extend/2","deprecated":false,"title":"extend(R, JsonObj)","anchor":"extend/2"},{"id":"extend/3","deprecated":false,"title":"extend(Key, Value, JsonObj)","anchor":"extend/3"},{"id":"get_id/1","deprecated":false,"title":"get_id(Doc)","anchor":"get_id/1"},{"id":"get_idrev/1","deprecated":false,"title":"get_idrev(Doc)","anchor":"get_idrev/1"},{"id":"get_rev/1","deprecated":false,"title":"get_rev(Doc)","anchor":"get_rev/1"},{"id":"get_value/2","deprecated":false,"title":"get_value(Key, JsonObj)","anchor":"get_value/2"},{"id":"get_value/3","deprecated":false,"title":"get_value(Key, JsonObj, Default)","anchor":"get_value/3"},{"id":"is_saved/1","deprecated":false,"title":"is_saved(Doc)","anchor":"is_saved/1"},{"id":"set_value/3","deprecated":false,"title":"set_value(Key, Value, JsonObj)","anchor":"set_value/3"},{"id":"take_value/2","deprecated":false,"title":"take_value(Key, JsonObj)","anchor":"take_value/2"},{"id":"take_value/3","deprecated":false,"title":"take_value(Key, JsonObj, Default)","anchor":"take_value/3"}],"key":"functions"}]},{"id":"couchbeam_ejson","deprecated":false,"group":"","title":"couchbeam_ejson","sections":[],"nodeGroups":[{"name":"Types","nodes":[{"id":"ejson/0","deprecated":false,"title":"ejson/0","anchor":"t:ejson/0"},{"id":"ejson_array/0","deprecated":false,"title":"ejson_array/0","anchor":"t:ejson_array/0"},{"id":"ejson_number/0","deprecated":false,"title":"ejson_number/0","anchor":"t:ejson_number/0"},{"id":"ejson_object/0","deprecated":false,"title":"ejson_object/0","anchor":"t:ejson_object/0"},{"id":"ejson_string/0","deprecated":false,"title":"ejson_string/0","anchor":"t:ejson_string/0"},{"id":"ejson_term/0","deprecated":false,"title":"ejson_term/0","anchor":"t:ejson_term/0"}],"key":"types"},{"name":"Functions","nodes":[{"id":"decode/1","deprecated":false,"title":"decode(D)","anchor":"decode/1"},{"id":"encode/1","deprecated":false,"title":"encode(D)","anchor":"encode/1"},{"id":"post_decode/1","deprecated":false,"title":"post_decode(Term)","anchor":"post_decode/1"}],"key":"functions"}]},{"id":"couchbeam_httpc","deprecated":false,"group":"","title":"couchbeam_httpc","sections":[],"nodeGroups":[{"name":"Types","nodes":[{"id":"db/0","deprecated":false,"title":"db/0","anchor":"t:db/0"},{"id":"server/0","deprecated":false,"title":"server/0","anchor":"t:server/0"}],"key":"types"},{"name":"Functions","nodes":[{"id":"db_request/5","deprecated":false,"title":"db_request(Method, Url, Headers, Body, Options)","anchor":"db_request/5"},{"id":"db_request/6","deprecated":false,"title":"db_request(Method, Url, Headers, Body, Options, Expect)","anchor":"db_request/6"},{"id":"db_resp/2","deprecated":false,"title":"db_resp(Resp, Expect)","anchor":"db_resp/2"},{"id":"db_url/1","deprecated":false,"title":"db_url(Db)","anchor":"db_url/1"},{"id":"doc_url/2","deprecated":false,"title":"doc_url(Db, DocId)","anchor":"doc_url/2"},{"id":"json_body/1","deprecated":false,"title":"json_body(Ref)","anchor":"json_body/1"},{"id":"make_headers/4","deprecated":false,"title":"make_headers(Method, Url, Headers, Options)","anchor":"make_headers/4"},{"id":"maybe_oauth_header/4","deprecated":false,"title":"maybe_oauth_header(Method, Url, Headers, Options)","anchor":"maybe_oauth_header/4"},{"id":"request/5","deprecated":false,"title":"request(Method, Url, Headers, Body, Options)","anchor":"request/5"},{"id":"server_url/1","deprecated":false,"title":"server_url(Server)","anchor":"server_url/1"}],"key":"functions"}]},{"id":"couchbeam_sup","deprecated":false,"group":"","title":"couchbeam_sup","sections":[],"nodeGroups":[{"name":"Functions","nodes":[{"id":"init/1","deprecated":false,"title":"init(_)","anchor":"init/1"},{"id":"start_link/0","deprecated":false,"title":"start_link()","anchor":"start_link/0"}],"key":"functions"}]},{"id":"couchbeam_util","deprecated":false,"group":"","title":"couchbeam_util","sections":[],"nodeGroups":[{"name":"Functions","nodes":[{"id":"binary_env/2","deprecated":false,"title":"binary_env(Key, Default)","anchor":"binary_env/2"},{"id":"dbname/1","deprecated":false,"title":"dbname(DbName)","anchor":"dbname/1"},{"id":"deprecated/3","deprecated":false,"title":"deprecated(Old, New, When)","anchor":"deprecated/3"},{"id":"encode_att_name/1","deprecated":false,"title":"encode_att_name(Name)","anchor":"encode_att_name/1"},{"id":"encode_docid1/1","deprecated":false,"title":"encode_docid1(DocId)","anchor":"encode_docid1/1"},{"id":"encode_docid/1","deprecated":false,"title":"encode_docid(DocId)","anchor":"encode_docid/1"},{"id":"encode_docid_noop/1","deprecated":false,"title":"encode_docid_noop(DocId)","anchor":"encode_docid_noop/1"},{"id":"encode_query/1","deprecated":false,"title":"encode_query(QSL)","anchor":"encode_query/1"},{"id":"encode_query_value/2","deprecated":false,"title":"encode_query_value(K, V)","anchor":"encode_query_value/2"},{"id":"force_param/3","deprecated":false,"title":"force_param(Key, Value, Options)","anchor":"force_param/3"},{"id":"get_app_env/2","deprecated":false,"title":"get_app_env(Env, Default)","anchor":"get_app_env/2"},{"id":"get_value/2","deprecated":false,"title":"get_value(Key, Prop)","anchor":"get_value/2"},{"id":"get_value/3","deprecated":false,"title":"get_value(Key, Prop, Default)","anchor":"get_value/3"},{"id":"oauth_header/3","deprecated":false,"title":"oauth_header(Url, Action, OauthProps)","anchor":"oauth_header/3"},{"id":"parse_options/1","deprecated":false,"title":"parse_options(Options)","anchor":"parse_options/1"},{"id":"parse_options/2","deprecated":false,"title":"parse_options(Rest, Acc)","anchor":"parse_options/2"},{"id":"propmerge1/2","deprecated":false,"title":"propmerge1(L1, L2)","anchor":"propmerge1/2"},{"id":"propmerge/3","deprecated":false,"title":"propmerge(F, L1, L2)","anchor":"propmerge/3"},{"id":"proxy_header/3","deprecated":false,"title":"proxy_header(UserName, Roles, Secret)","anchor":"proxy_header/3"},{"id":"proxy_token/2","deprecated":false,"title":"proxy_token(Secret, UserName)","anchor":"proxy_token/2"},{"id":"shutdown_sync/1","deprecated":false,"title":"shutdown_sync(Pid)","anchor":"shutdown_sync/1"},{"id":"start_app_deps/1","deprecated":false,"title":"start_app_deps(App)","anchor":"start_app_deps/1"},{"id":"to_atom/1","deprecated":false,"title":"to_atom(V)","anchor":"to_atom/1"},{"id":"to_binary/1","deprecated":false,"title":"to_binary(V)","anchor":"to_binary/1"},{"id":"to_integer/1","deprecated":false,"title":"to_integer(V)","anchor":"to_integer/1"},{"id":"to_list/1","deprecated":false,"title":"to_list(V)","anchor":"to_list/1"}],"key":"functions"}]},{"id":"couchbeam_uuids","deprecated":false,"group":"","title":"couchbeam_uuids","sections":[],"nodeGroups":[{"name":"Types","nodes":[{"id":"server/0","deprecated":false,"title":"server/0","anchor":"t:server/0"}],"key":"types"},{"name":"Functions","nodes":[{"id":"code_change/3","deprecated":false,"title":"code_change(OldVsn, State, Extra)","anchor":"code_change/3"},{"id":"get_uuids/2","deprecated":false,"title":"get_uuids(Server, Count)","anchor":"get_uuids/2"},{"id":"handle_call/3","deprecated":false,"title":"handle_call(_, From, State)","anchor":"handle_call/3"},{"id":"handle_cast/2","deprecated":false,"title":"handle_cast(Msg, State)","anchor":"handle_cast/2"},{"id":"handle_info/2","deprecated":false,"title":"handle_info(Info, State)","anchor":"handle_info/2"},{"id":"init/1","deprecated":false,"title":"init(_)","anchor":"init/1"},{"id":"random/0","deprecated":false,"title":"random()","anchor":"random/0"},{"id":"start_link/0","deprecated":false,"title":"start_link()","anchor":"start_link/0"},{"id":"terminate/2","deprecated":false,"title":"terminate(Reason, State)","anchor":"terminate/2"},{"id":"utc_random/0","deprecated":false,"title":"utc_random()","anchor":"utc_random/0"}],"key":"functions"}]},{"id":"couchbeam_view","deprecated":false,"group":"","title":"couchbeam_view","sections":[],"nodeGroups":[{"name":"Types","nodes":[{"id":"db/0","deprecated":false,"title":"db/0","anchor":"t:db/0"},{"id":"design_name/0","deprecated":false,"title":"design_name/0","anchor":"t:design_name/0"},{"id":"ejson_object/0","deprecated":false,"title":"ejson_object/0","anchor":"t:ejson_object/0"},{"id":"server/0","deprecated":false,"title":"server/0","anchor":"t:server/0"},{"id":"show_option/0","deprecated":false,"title":"show_option/0","anchor":"t:show_option/0"},{"id":"show_options/0","deprecated":false,"title":"show_options/0","anchor":"t:show_options/0"},{"id":"stale/0","deprecated":false,"title":"stale/0","anchor":"t:stale/0"},{"id":"view_name/0","deprecated":false,"title":"view_name/0","anchor":"t:view_name/0"},{"id":"view_option/0","deprecated":false,"title":"view_option/0","anchor":"t:view_option/0"},{"id":"view_options/0","deprecated":false,"title":"view_options/0","anchor":"t:view_options/0"},{"id":"view_query_args/0","deprecated":false,"title":"view_query_args/0","anchor":"t:view_query_args/0"}],"key":"types"},{"name":"Functions","nodes":[{"id":"all/1","deprecated":false,"title":"all(Db)","anchor":"all/1"},{"id":"all/2","deprecated":false,"title":"all(Db, Options)","anchor":"all/2"},{"id":"cancel_stream/1","deprecated":false,"title":"cancel_stream(Ref)","anchor":"cancel_stream/1"},{"id":"count/1","deprecated":false,"title":"count(Db)","anchor":"count/1"},{"id":"count/2","deprecated":false,"title":"count(Db, ViewName)","anchor":"count/2"},{"id":"count/3","deprecated":false,"title":"count(Db, ViewName, Options)","anchor":"count/3"},{"id":"fetch/1","deprecated":false,"title":"fetch(Db)","anchor":"fetch/1"},{"id":"fetch/2","deprecated":false,"title":"fetch(Db, ViewName)","anchor":"fetch/2"},{"id":"fetch/3","deprecated":false,"title":"fetch(Db, ViewName, Options)","anchor":"fetch/3"},{"id":"first/1","deprecated":false,"title":"first(Db)","anchor":"first/1"},{"id":"first/2","deprecated":false,"title":"first(Db, ViewName)","anchor":"first/2"},{"id":"first/3","deprecated":false,"title":"first(Db, ViewName, Options)","anchor":"first/3"},{"id":"fold/4","deprecated":false,"title":"fold(Function, Acc, Db, ViewName)","anchor":"fold/4"},{"id":"fold/5","deprecated":false,"title":"fold(Function, Acc, Db, ViewName, Options)","anchor":"fold/5"},{"id":"foreach/3","deprecated":false,"title":"foreach(Function, Db, ViewName)","anchor":"foreach/3"},{"id":"foreach/4","deprecated":false,"title":"foreach(Function, Db, ViewName, Options)","anchor":"foreach/4"},{"id":"parse_view_options/1","deprecated":false,"title":"parse_view_options(Options)","anchor":"parse_view_options/1"},{"id":"show/2","deprecated":false,"title":"show(Db, ShowName)","anchor":"show/2"},{"id":"show/3","deprecated":false,"title":"show(Db, ShowName, DocId)","anchor":"show/3"},{"id":"show/4","deprecated":false,"title":"show(Db, _, DocId, Options)","anchor":"show/4"},{"id":"stream/2","deprecated":false,"title":"stream(Db, ViewName)","anchor":"stream/2"},{"id":"stream/3","deprecated":false,"title":"stream(Db, ViewName, Options)","anchor":"stream/3"},{"id":"stream_next/1","deprecated":false,"title":"stream_next(Ref)","anchor":"stream_next/1"}],"key":"functions"}]},{"id":"couchbeam_view_stream","deprecated":false,"group":"","title":"couchbeam_view_stream","sections":[],"nodeGroups":[{"name":"Functions","nodes":[{"id":"init_stream/5","deprecated":false,"title":"init_stream(Parent, Owner, StreamRef, Req, StreamOptions)","anchor":"init_stream/5"},{"id":"maybe_continue/1","deprecated":false,"title":"maybe_continue(State)","anchor":"maybe_continue/1"},{"id":"start_link/4","deprecated":false,"title":"start_link(Owner, StreamRef, _, StreamOptions)","anchor":"start_link/4"},{"id":"system_code_change/4","deprecated":false,"title":"system_code_change(Misc, _, _, _)","anchor":"system_code_change/4"},{"id":"system_continue/3","deprecated":false,"title":"system_continue(_, _, _)","anchor":"system_continue/3"},{"id":"system_terminate/4","deprecated":false,"title":"system_terminate(Reason, _, _, State)","anchor":"system_terminate/4"}],"key":"functions"}]},{"id":"couchbeam_view_sup","deprecated":false,"group":"","title":"couchbeam_view_sup","sections":[],"nodeGroups":[{"name":"Functions","nodes":[{"id":"init/1","deprecated":false,"title":"init(_)","anchor":"init/1"},{"id":"start_link/0","deprecated":false,"title":"start_link()","anchor":"start_link/0"}],"key":"functions"}]},{"id":"gen_changes","deprecated":false,"group":"","title":"gen_changes","sections":[],"nodeGroups":[{"name":"Functions","nodes":[{"id":"behaviour_info/1","deprecated":false,"title":"behaviour_info(_)","anchor":"behaviour_info/1"},{"id":"call/2","deprecated":false,"title":"call(Name, Request)","anchor":"call/2"},{"id":"call/3","deprecated":false,"title":"call(Name, Request, Timeout)","anchor":"call/3"},{"id":"cast/2","deprecated":false,"title":"cast(Dest, Request)","anchor":"cast/2"},{"id":"code_change/3","deprecated":false,"title":"code_change(OldVersion, State, Extra)","anchor":"code_change/3"},{"id":"get_seq/1","deprecated":false,"title":"get_seq(Pid)","anchor":"get_seq/1"},{"id":"handle_call/3","deprecated":false,"title":"handle_call(Request, From, State)","anchor":"handle_call/3"},{"id":"handle_cast/2","deprecated":false,"title":"handle_cast(Msg, State)","anchor":"handle_cast/2"},{"id":"handle_info/2","deprecated":false,"title":"handle_info(Info, State)","anchor":"handle_info/2"},{"id":"init/1","deprecated":false,"title":"init(_)","anchor":"init/1"},{"id":"start_link/4","deprecated":false,"title":"start_link(Module, Db, Options, InitArgs)","anchor":"start_link/4"},{"id":"stop/1","deprecated":false,"title":"stop(Pid)","anchor":"stop/1"},{"id":"terminate/2","deprecated":false,"title":"terminate(Reason, Gen_changes_state)","anchor":"terminate/2"}],"key":"functions"}]},{"id":"json_stream_parse","deprecated":false,"group":"","title":"json_stream_parse","sections":[],"nodeGroups":[{"name":"Functions","nodes":[{"id":"feed/2","deprecated":false,"title":"feed(Data, St)","anchor":"feed/2"},{"id":"finish/1","deprecated":false,"title":"finish(S)","anchor":"finish/1"},{"id":"init/0","deprecated":false,"title":"init()","anchor":"init/0"}],"key":"functions"}]}],"extras":[{"id":"api-reference","group":"","title":"API Reference","headers":[{"id":"Modules","anchor":"modules"}]},{"id":"readme","group":"","title":"Readme","headers":[{"id":"Installation","anchor":"installation"},{"id":"Basic Usage","anchor":"basic-usage"},{"id":"Contribute","anchor":"contribute"}]},{"id":"news","group":"","title":"Changelog","headers":[{"id":"couchbeam NEWS","anchor":"couchbeam-news"},{"id":"version 2.0.0 / 2025-09-03","anchor":"version-2-0-0-2025-09-03"},{"id":"version 1.7.1 / 2025-07-24","anchor":"version-1-7-1-2025-07-24"},{"id":"version 1.7.0 / 2025-05-28","anchor":"version-1-7-0-2025-05-28"},{"id":"version 1.6.0 / 2025-01-26","anchor":"version-1-6-0-2025-01-26"},{"id":"version 1.5.4 / 2025-02-20","anchor":"version-1-5-4-2025-02-20"},{"id":"version 1.5.3 / 2024-08-20","anchor":"version-1-5-3-2024-08-20"},{"id":"version 1.5.1 / 2024-11-07","anchor":"version-1-5-1-2024-11-07"},{"id":"version 1.5.1 / 2024-11-07","anchor":"version-1-5-1-2024-11-07-1"},{"id":"version 1.5.0 / 2023-10-11","anchor":"version-1-5-0-2023-10-11"},{"id":"version 1.4.1 / 2016-09-26","anchor":"version-1-4-1-2016-09-26"},{"id":"version 1.4.0 / 2016-09-22","anchor":"version-1-4-0-2016-09-22"},{"id":"version 1.3.1 / 2016-07-01","anchor":"version-1-3-1-2016-07-01"},{"id":"version 1.3.0 / 2016-03-22","anchor":"version-1-3-0-2016-03-22"},{"id":"version 1.2.1 / 2015/11/04","anchor":"version-1-2-1-2015-11-04"},{"id":"version 1.2.0 / 2015/11/04","anchor":"version-1-2-0-2015-11-04"},{"id":"version 1.1.8 / 2015-08-27","anchor":"version-1-1-8-2015-08-27"},{"id":"version 1.1.7 / 2015-03-11","anchor":"version-1-1-7-2015-03-11"},{"id":"version 1.1.6 / 2015-01-02","anchor":"version-1-1-6-2015-01-02"},{"id":"version 1.1.5 / 2014-12-09","anchor":"version-1-1-5-2014-12-09"},{"id":"version 1.1.4 / 2014-12-01","anchor":"version-1-1-4-2014-12-01"},{"id":"version 1.1.3 / 2014-11-30","anchor":"version-1-1-3-2014-11-30"},{"id":"version 1.1.2 / 2014-11-15","anchor":"version-1-1-2-2014-11-15"},{"id":"version 1.1.1 / 2014-11-11","anchor":"version-1-1-1-2014-11-11"},{"id":"version 1.1.0 / 2014-10-28","anchor":"version-1-1-0-2014-10-28"},{"id":"version 1.0.7 / 2014-07-08","anchor":"version-1-0-7-2014-07-08"},{"id":"version 1.0.6 / 2014-04-18","anchor":"version-1-0-6-2014-04-18"},{"id":"version 1.0.5 / 2014-04-18","anchor":"version-1-0-5-2014-04-18"},{"id":"version 1.0.4 / 2014-04-15","anchor":"version-1-0-4-2014-04-15"},{"id":"version 1.0.3 / 2014-04-15","anchor":"version-1-0-3-2014-04-15"},{"id":"version 1.0.2 / 2014-01-03","anchor":"version-1-0-2-2014-01-03"},{"id":"version 1.0.1 / 2013-12-30","anchor":"version-1-0-1-2013-12-30"},{"id":"version 1.0.0 / 2013-12-21","anchor":"version-1-0-0-2013-12-21"},{"id":"version 0.10.0 / 2013-12-21","anchor":"version-0-10-0-2013-12-21"},{"id":"version 0.9.3 / 2013-12-07","anchor":"version-0-9-3-2013-12-07"},{"id":"version 0.9.2 / 2013-12-07","anchor":"version-0-9-2-2013-12-07"},{"id":"version 0.9.1 / 2013-12-05","anchor":"version-0-9-1-2013-12-05"},{"id":"version 0.9.0 / 2013-12-05","anchor":"version-0-9-0-2013-12-05"},{"id":"version 0.7.0 / 2011-07-05","anchor":"version-0-7-0-2011-07-05"}]},{"id":"notice","group":"","title":"Notice","headers":[]},{"id":"license","group":"","title":"License","headers":[]}],"tasks":[]} \ No newline at end of file diff --git a/site/gen_changes.html b/site/gen_changes.html deleted file mode 100644 index 80e87e9a..00000000 --- a/site/gen_changes.html +++ /dev/null @@ -1,554 +0,0 @@ - - - - - - - - - - - gen_changes — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - -
-
-

- gen_changes behaviour - (couchbeam v2.0.0) - -

- - - - View Source - - -
- - -
-

gen_changes CouchDB continuous changes consumer behavior This behaviour allows you to create easily a server that consume Couchdb continuous changes

-
- -
- -
-

- - - - Summary -

-
-

- Functions -

- -
- - -
- -
- - -
- - - -
- - -
- - - -
-
- get_seq(Pid) - -
- -
- - - - - - - -
-
- init(_) - -
- -
- -
- - -

create a gen_changes process as part of a supervision tree. The function should be called, directly or indirectly, by the supervisor. InitArgs::list()) -> term() changesoptions() = [changeoption()] changeoption() = {include_docs, string()} | {filter, string()} | {since, integer()|string()} | {heartbeat, string()|boolean()}

- -
- -
-
- stop(Pid) - -
- -
- - - -
- -
- - -
-

- - - - Functions -

-
-
- -
- - - -
-

behaviour_info(_)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

call(Name, Request)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

call(Name, Request, Timeout)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

cast(Dest, Request)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

code_change(OldVersion, State, Extra)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

get_seq(Pid)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

handle_call(Request, From, State)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

handle_cast(Msg, State)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

handle_info(Info, State)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

init(_)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

start_link(Module, Db, Options, InitArgs)

- - - - - - -
-
- -
- -

create a gen_changes process as part of a supervision tree. The function should be called, directly or indirectly, by the supervisor. InitArgs::list()) -> term() changesoptions() = [changeoption()] changeoption() = {include_docs, string()} | {filter, string()} | {since, integer()|string()} | {heartbeat, string()|boolean()}

-
-
-
- -
- - - -
-

stop(Pid)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

terminate(Reason, Gen_changes_state)

- - - - - - -
-
- -
- - -
-
- -
-
- - -
-
-
- - - diff --git a/site/index.html b/site/index.html deleted file mode 100644 index 6ad5c4bb..00000000 --- a/site/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - couchbeam v2.0.0 — Documentation - - - - - diff --git a/site/json_stream_parse.html b/site/json_stream_parse.html deleted file mode 100644 index c08505d4..00000000 --- a/site/json_stream_parse.html +++ /dev/null @@ -1,248 +0,0 @@ - - - - - - - - - - - json_stream_parse — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - -
-
-

- json_stream_parse - (couchbeam v2.0.0) - -

- - - - View Source - - -
- - -
- -
-

- - - - Summary -

-
-

- Functions -

- -
- - -
- -
-
- finish(S) - -
- -
- -
-
- init() - -
- -
- -
- -
- - -
-

- - - - Functions -

-
-
- -
- - - -
-

feed(Data, St)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

finish(S)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

init()

- - - - - - -
-
- -
- - -
-
- -
-
- - -
-
-
- - - diff --git a/site/license.html b/site/license.html deleted file mode 100644 index 9deed1dc..00000000 --- a/site/license.html +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - License — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - -
-
-

License

- - - - - View Source - - -
- - -
-2009-2025 (c) Benoit Chesneau
-
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
- -
- - - -
-
-
- - - diff --git a/site/news.html b/site/news.html deleted file mode 100644 index 72b49db8..00000000 --- a/site/news.html +++ /dev/null @@ -1,192 +0,0 @@ - - - - - - - - - - - Changelog — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - -
-
-

Changelog

- - - - - View Source - - -
- - -

couchbeam NEWS

version 2.0.0 / 2025-09-03

  • move from propos lists to maps for json
  • remove JSX & Jiffy Usage for erlang/0TP 28.0+ json module
  • View and changes streaming now use a simpler parser

BREAKING CHANGE

  • move to maps, you will need to migrate your application to use them. -no backward compatibility is provided

version 1.7.1 / 2025-07-24

  • update hackney depdendency to 1.25.0

version 1.7.0 / 2025-05-28

  • fix resource leaks and race conditions in stream modules
  • fix unclosed hackney connections on error paths
  • add proper cleanup for monitor references using try-finally
  • fix ETS table race conditions by checking process liveness
  • improve stream initialization order to prevent races
  • add error handling for hackney operations to prevent leaks
  • fix changes stream registration race condition by registering before parent notification

version 1.6.0 / 2025-01-26

  • add support for CouchDB _find endpoint
  • add ability to query _show functions
  • add option for disabling view_stream usage (enabled by default)
  • fix error handling in gen_changes callback handling
  • fix resource cleanup in stream modules to prevent connection leaks
  • improve replication test reliability and timeout handling
  • update hackney dependency to 1.23
  • update jsx dependency
  • add GitHub Actions for CouchDB testing
  • fix dialyzer complaints and pattern matching issues
  • OTP 27 compatibility improvements

version 1.5.4 / 2025-02-20

  • bump hackney 1.22.0

version 1.5.3 / 2024-08-20

  • fix packaging

version 1.5.1 / 2024-11-07

  • fix pattern matching

version 1.5.1 / 2024-11-07

  • fix: handle condition that may cause persistent CLOSE-WAIT sockets

version 1.5.0 / 2023-10-11

  • use hackney 1.20.0
  • fix compatibility with couchdb 3
  • fix compatibility with Erlang >= 23

version 1.4.1 / 2016-09-26

  • maintainance update

version 1.4.0 / 2016-09-22

  • maintainance update.

version 1.3.1 / 2016-07-01

  • fix: accept 202 status in couchbeam:save_doc/4 function (#144)
  • fix: spec syntax to build with Erlang 19 (#145)

version 1.3.0 / 2016-03-22

version 1.2.1 / 2015/11/04

  • also support hackney 1.4.4 for rebar2.
  • fix hex.pm release to really use 1.4.4

version 1.2.0 / 2015/11/04

  • move to eunit for tests.
  • hex.pm support
  • mix & rebar3 build tools support
  • bump hackney to 1.4.4
  • bump jsx to 2.2.8

Breaking change

erlang-oauth is now optionnal and won't be installed by default.

version 1.1.8 / 2015-08-27

  • use latest stable branch of hackney

version 1.1.7 / 2015-03-11

  • bump hackney to 1.1.0
  • fix Conten-Type header ehen posting doc IDS in changes #126
  • fix documentation

version 1.1.6 / 2015-01-02

  • fix included_applications (#122)

version 1.1.5 / 2014-12-09

  • improvement: do not force connections options to nodelay
  • update to Hackney 1.0.4 fix #120
  • fix: retry fecthing UUIDS on error (#121)

version 1.1.4 / 2014-12-01

  • update to Hackney 1.0.1: more SSL -certificate authority handling.
  • fix: changes stream

version 1.1.3 / 2014-11-30

version 1.1.2 / 2014-11-15

  • remove spurious prints

version 1.1.1 / 2014-11-11

version 1.1.0 / 2014-10-28

  • update to hackney 0.14.3
  • fix memory leaks
  • correctly close sockets
  • fix streaming issue: don't wait the stream timeout to report the initial -error.
  • update JSX dependency to version 2.1.1

version 1.0.7 / 2014-07-08

version 1.0.6 / 2014-04-18

version 1.0.5 / 2014-04-18

  • improve connections with HTTP proxies
  • improve content-types detection of attachments
  • improve URL encoding normalzation, useful when connecting to an -international domain/URI
  • URL resolving is faster
  • bump to hackney 0.12.0

version 1.0.4 / 2014-04-15

  • remove spurious print

version 1.0.3 / 2014-04-15

  • add support for the new_edits option in bulk doc API.
  • improvement: send a doc as multipart that already contains attachments
  • bump hackney to 0.11.2
  • fix path encoding

version 1.0.2 / 2014-01-03

  • fix: send a doc as multipart that already contains attachments

version 1.0.1 / 2013-12-30

  • fix connection reusing in changes and view streams
  • bump hackney version to 0.10.1

version 1.0.0 / 2013-12-21

First stable release. This is a supported release.

  • send a doc and its attachments efficiently using the multipart -API.
  • add couchbeam:get_config/{1,2,3}, couchbeam:set_config/{4,5} and -couchbeam:delete_config/{3,4} to use the config -API.
  • add couchbeam_uuids:random/0 and couchbeam_uuids:utc_random/0 to -generate UUIDS in your app instead of reusing the UUID generated on -the node. By default couchbeam is fetching from the node, which is
  • add {error, forbidden} and {error, unauthenticated} as possible -results of a reply. -better if you want to use UUID based on the node time.
  • fix accept header handling

version 0.10.0 / 2013-12-21

  • add couchbeam:copy_doc/{2,3} to support the COPY API
  • add couchbeam:get_missing_revs/2 to get the list of missing -revisions
  • add support of the multipart -API when fetching a doc: This change make -couchbeam:open_doc/3 returns a multipart response {ok, {multipart, Stream}} -when using the attachments=true option. A new option {accept, <<"multipart/mixed">>} -can also be used with the options open_revs or revs to fetch the response as a multipart.
  • bump the hackney version to -0.9.1 .

With this change you can now efficiently retrieve a doc with all of its -attachments or a doc wit all its revisions. - master

version 0.9.3 / 2013-12-07

  • fix: couchbeam:open_or_create_db/2

version 0.9.2 / 2013-12-07

  • bump hackney version to 0.8.3

version 0.9.1 / 2013-12-05

  • fix design docid encoding

version 0.9.0 / 2013-12-05

This is a major release pre-1.0. API is now frozen and won't change much -until the version 1.0.

  • replaced the use of ibrowse by hackney to handle HTTP connections
  • new streaming -API in view
  • breaking change: remobe
  • breaking change: remove deprecated view API. Everything is now managed in the -couch_view module.
  • replace 'couchbeam_changes:stream' and 'couchbeam_changes:fetch' -functions by 'couchbeam_changes/follow' and 'couchbeam_changes:follow_once'.
  • breaking change: new attachment API
  • new: JSX a pure erlang JSON encoder/decoder is now the default. Jiffy -can be set at the compilation by defining 'WITH_JIFFY' in the Erlang -options.
  • removed mochiweb dependency.

version 0.7.0 / 2011-07-05

This release contains backwards incompatible changes.

  • New and more efficient couchbeam_changes API, we now parse json stream -instead of the try catch steps we used before.
  • New and more efficient couchbeam_view API. we now parse json stream -instead of getting all results. New couchbeam_view:stream and -couchbeam_view fetch functions have been added. We also don't use any -more a view record in other functions
  • HTTP functions have been moved to couchbeam_httpc modules
  • gen_changes behaviour has been updated to use the couchbeam_changes -API. It's also abble to restart a lost connection for longpoll and -continuous feeds.

Breaking Changes:

  • couchbeam:view and couchbeam:all_docs have been deprecated. Old views -functions using the #view{} record from these functions have been -moved in couchbeam_oldview module.
  • couchbeam:wait_changes, couchbeam:wait_changes_once, couchbeam:changes -functions have been deprecated and are now replaced by -couchbeam_changes:stream and couchbeam_changes:fetch functions.
- -
- - - -
-
-
- - - diff --git a/site/notice.html b/site/notice.html deleted file mode 100644 index d14e6b81..00000000 --- a/site/notice.html +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - - - - - - Notice — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - -
-
-

Notice

- - - - - View Source - - -
- - -
-Couchbeam
----------
-
-2009-2025 (c) Benoit Chesneau
-
-couchbeam is released under the MIT license. See the LICENSE file for the
-complete license.
-
- -
- - - -
-
-
- - - diff --git a/site/readme.html b/site/readme.html deleted file mode 100644 index 31be4f41..00000000 --- a/site/readme.html +++ /dev/null @@ -1,294 +0,0 @@ - - - - - - - - - - - Readme — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - -
-
-

Couchbeam - simple Apache CouchDB client library for Erlang applications

- - - - - View Source - - -
- - -

Copyright (c) 2009-2025 Benoit Chesneau.

Version: 1.7.1

couchbeam

Couchbeam is a simple erlang library for Barrel or Apache CouchDB. Couchbeam provides you a full featured and easy client to access and manage multiple nodes.

Main features:

  • Complete support of the BarrelDB and Apache CouchDB API
  • Stream view results to your app
  • Stream changes feeds
  • reduced memory usage
  • fetch and send attachments in a streaming fashion
  • JSON encoding/decoding via Erlang/OTP stdlib json with maps

Useful modules are:

  • couchbeam: The couchbeam module is the main interface for interaction with this application. It includes functions for managing connections to Apache CouchDB or RCOUCH servers and databases and for performing document creations, updates, deletes, views...
  • couchbeam_doc Module to manipulate Documents structures. You can set values, -updates keys, ...
  • couchbeam_attachments: Module to manipulate attachments. You can add, remove -attachments in a Document structure (inline attachments).
  • couchbeam_view: Module to manage view results.
  • couchbeam_changes: Module to manage changes feeds. Follow continuously -the changes in a db or get all changes at once.

The goal of Couchbeam is to ease the access to the Apache CouchDB and RCOUCH HTTP API in erlang.

Read the NEWS file -to get last changelog.

Installation

Download the sources from our Github repository

To build the application simply run 'make'. This should build .beam, .app -files and documentation.

To run tests run 'make test'. -To generate doc, run 'make doc'.

Or add it to your rebar config

   erlang
-{deps, [
-    ....
-    {couchbeam, ".*", {git, "git://github.com/benoitc/couchbeam.git", {branch, "master"}}}
-]}.

Note to compile with jiffy you need to define in the erlang options the -variable WITH_JIFFY.

if you use rebar, add to your rebar.config:

   erlang
-{erl_opts, [{d, 'WITH_JIFFY'}]}.

or use the rebar command with the -D options:

   sh
-rebar compile -DWITH_JIFFY

Basic Usage

Start couchbeam

Couchbeam is an OTP -application. You have to start it first before using any of the -functions. The couchbeam application will start the default socket pool -for you.

To start in the console run:

   sh
-$ erl -pa ebin
-1> couchbeam:start().
-ok

It will start hackney and all of the application it depends on:

   erlang
-application:start(crypto),
-application:start(asn1),
-application:start(public_key),
-application:start(ssl),
-application:start(hackney),
-application:start(couchbeam).

Or add couchbeam to the applications property of your .app in a release

Create a connection to the server

To create a connection to a server machine:

   erlang
-Url = "http://localhost:5984",
-Options = [],
-S = couchbeam:server_connection(Url, Options).

Test the connection with couchbeam:server_info/1 :

   erlang
-{ok, _Version} = couchbeam:server_info(S).

Open or Create a database

All document operations are done in databases. To open a database simply do:

   erlang
-Options = [],
-{ok, Db} = couchbeam:open_db(Server, "testdb", Options).

To create a new one:

   erlang
-Options = [],
-{ok, Db} = couchbeam:create_db(Server, "testdb", Options).

You can also use the shorcut couchbeam:open_or_create_db/3. that -will create a database if it does not exist.

Make a new document

Make a new document:

   erlang
-Doc = #{
-    <<"_id">> => <<"test">>,
-    <<"content">> => <<"some text">>
-}.

And save it to the database:

   erlang
-{ok, Doc1} = couchbeam:save_doc(Db, Doc).

The couchbeam:save_doc/2 return a new document with updated -revision and if you do not specify the _id, a unique document id.

To change an document property use functions from couchbeam_doc.

Retrieve a document

To retrieve a document do:

   erlang
-{ok, Doc2} = couchbeam:open_doc(Db, "test").

If you want a specific revision:

   erlang
-Rev = couchbeam_doc:get_rev(Doc1),
-Options = [{rev, Rev}],
-{ok, Doc3} = couchbeam:open_doc(Db, "test", Options).

Here we get the revision from the document we previously stored. Any -options from the Apache CouchDB and RCOUCH API can be used.

Get all documents

To get all documents you have first to create an object -that will keep all informations.

   erlang
-Options = [include_docs],
-{ok, AllDocs} = couchbeam_view:all(Db, Options).

Example result (abridged):

   erlang
-{ok, [
-    #{
-      <<"id">> => <<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>,
-      <<"key">> => <<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>,
-      <<"value">> => #{<<"rev">> => <<"15-15c0b3c4efa74f9a80d28ac040f18bdb">>},
-      <<"doc">> => #{
-        <<"_id">> => <<"7a0ce91d0d0c5e5b51e904d1ee3266a3">>,
-        <<"_rev">> => <<"15-15c0b3c4efa74f9a80d28ac040f18"...>>
-      }
-    }
-]}.

All functions to manipulate these results are in the couchbeam_view module.

Couch DB views

Views are workin like all_docs. You have to create a View object before -doing anything.

   erlang
-Options = [],
-DesignName = "designname",
-ViewName = "viewname",
-{ok, ViewResults} = couchbeam_view:fetch(Db, {DesignName, ViewName}, Options).

Like the all_docs function, use the functions -from couchbeam_view module to manipulate results. You can pass -any querying options from the view API.

Design doc are created like any documents:

   erlang
-DesignDoc = #{
-    <<"_id">> => <<"_design/couchbeam">>,
-    <<"language">> => <<"javascript">>,
-    <<"views">> => #{
-        <<"test">> => #{
-            <<"map">> => <<"function (doc) {\n if (doc.type == \"test\") {\n emit(doc._id, doc);\n}\n}">>
-        },
-        <<"test2">> => #{
-            <<"map">> => <<"function (doc) {\n if (doc.type == \"test2\") {\n emit(doc._id, null);\n}\n}">>
-        }
-    }
-},
-{ok, DesignDoc1} = couchbeam:save_doc(Db, DesignDoc).

You can also use couchapp to manage them -more easily.

Stream View results

While you can get results using couchbeam_views:fetch/2, you can also retrieve -all rows in a streaming fashion:

   erlang
-ViewFun = fun(Ref, F) ->
-    receive
-        {Ref, done} ->
-            io:format("done", []),
-            done;
-        {Ref, {row, Row}} ->
-            io:format("got ~p~n", [Row]),
-            F(Ref, F);
-        {error, Ref, Error} ->
-            io:format("error: ~p~n", [Error])
-    end
-end,
-
-{ok, StreamRef} = couchbeam_view:stream(Db, 'all_docs'),
-ViewFun(StreamRef, ViewFun),
-{ok, StreamRef2} = couchbeam_view:stream(Db, 'all_docs', [include_docs]),
-ViewFun(StreamRef2, ViewFun).

You can of course do the same with a view:

   erlang
-DesignNam = "designname",
-ViewName = "viewname",
-{ok, StreamRef3} = couchbeam_view:stream(Db, {DesignNam, ViewName}, [include_docs]),
-ViewFun(StreamRef3, ViewFun).

Put, Fetch and Delete documents attachments

You can add attachments to any documents. Attachments could be anything.

To send an attachment:

   erlang
-DocID = "test",
-AttName = "test.txt",
-Att = "some content I want to attach",
-Options = []
-{ok, _Result} = couchbeam:put_attachment(Db, DocId, AttName, Att, Options).

All attachments are streamed to servers. Att could be also be an iolist -or functions, see couchbeam:put_attachment/5 for more information.

To fetch an attachment:

   erlang
-{ok Att1} = couchbeam:fetch_attachment(Db, DocId, AttName).

You can use couchbeam:stream_attachment/1 for the stream -fetch.

To delete an attachment:

   erlang
-{ok, Doc4} = couchbeam:open_doc(Db, DocID),
-ok = couchbeam:delete_attachment(Db, Doc4, AttName).

Changes

Apache CouchDB and RCOUCH provide a means to get a list of changes made to documents in -the database. With couchbeam you can get changes using couchbeam_changes:follow_once/2. -This function returns all changes immediately. But you can also retrieve -all changes rows using longpolling :

   erlang
-Options = [],
-{ok, LastSeq, Rows} = couchbeam_changes:follow_once(Db, Options).

Options can be any Changes query parameters. See the change API for more informations.

You can also get continuous:

   erlang
-ChangesFun = fun(StreamRef, F) ->
-    receive
-        {StreamRef, {done, LastSeq}} ->
-            io:format("stopped, last seq is ~p~n", [LastSeq]),
-            ok;
-        {StreamRef, {change, Change}} ->
-            io:format("change row ~p ~n", [Change]),
-            F(StreamRef, F);
-        {StreamRef, Error}->
-            io:format("error ? ~p ~n,", [Error])
-    end
-end,
-Options = [continuous, heartbeat],
-{ok, StreamRef} = couchbeam_changes:follow(Db, Options),
-ChangesFun(StreamRef, ChangesFun).

Note: a gen_changes behaviour exists in couchbeam that you can -use to create your own specific gen_server receiving changes. Have a -look in the -example -for more info.

Authentication/ Connections options

You can authenticate to the database or Apache CouchDB or RCOUCH server by filling -options to the Option list in couchbeam:server_connection/4 for the -server or in couchbeam:create_db/3, couchbeam:open_db/3, -couchbeam:open_or_create_db/3 functions.

To set basic_auth on a server:

   erlang
-UserName = "guest",
-Password = "test",
-Url = "http://localhost:5984",
-Options = [{basic_auth, {UserName, Password}}],
-S1 = couchbeam:server_connection(Url, Options).

Couchbeam support SSL, OAuth, Basic Authentication, and Proxy. You can -also set a cookie. For more informations about the options have a look -in the couchbeam:server_connection/2 documentation.

Contribute

For issues, comments or feedback please create an -issue.

- -
- - - -
-
-
- - - diff --git a/site/search.html b/site/search.html deleted file mode 100644 index 59ffd895..00000000 --- a/site/search.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - - - - - - - Search — couchbeam v2.0.0 - - - - - - - - - - - -
- - - - - - - -
-
- - - - - -
-
-
- - -
- - - - - - - -
-
- - -
-
-

- couchbeam - (couchbeam v2.0.0) - -

- - - - View Source - - -
- - -
- -
-

- - - - Summary -

-
-

- Types -

- -
-
- db/0 - -
- -
- -
-
- doc/0 - -
- -
- -
-
- doc_stream/0 - -
- -
- -
- - -
- -
- - -
- -
- - -
- -
-
- server/0 - -
- -
- -
-
-

- Functions -

- -
- - -

get list of databases on a CouchDB node

- -
- -
- - -

get list of databases on a CouchDB node with optional filter

- -
- -
-
- compact(Db) - -
- -

Compaction compresses the database file by removing unused sections created during updates. See http://wiki.apache.org/couchdb/Compaction for more informations

- -
- -
- - -

Like compact/1 but this compacts the view index from the current version of the design document. See http://wiki.apache.org/couchdb/Compaction#View_compaction for more informations

- -
- -
- - -

duplicate a document using the doc API

- -
- -
- - -

copy a doc to a destination. If the destination exist it will use the last revision, in other case a new doc is created with the the current doc revision.

- -
- - - - - -
- - -

Create a database and a client for connectiong to it.

- -
- -
- - -

test if db with dbname exists on the CouchDB node

- -
- -
-
- db_info(Db) - -
- -

get database info

- -
- - - -
- - -

delete a document attachment

- -
- -
- - - - -
- -
- - -

delete database

- -
- -
- - - - -
- -
- - -

delete a document if you want to make sure the doc it emptied on delete, use the option {empty_on_delete, true} or pass a doc with just _id and _rev members.

- -
- -
- - - - -
- -
- - -

delete a list of documents if you want to make sure the doc it emptied on delete, use the option {empty_on_delete, true} or pass a doc with just _id and _rev members.

- -
- - - -
- - -

test if doc with uuid exists in the given db

- -
- -
- - -

stop to receive the multipart response of the doc api and close the connection.

- -
- -
- - - - -
- -
- - -

commit all docs in memory

- -
- - - -
- - -

fetch a document attachment Options are

- -
- - - -
- - -

get missing revisions

- -
- -
- - -

Get one uuid from the server

- -
- -
- - -

Get a list of uuids from the server

- -
- -
- - -

get the last revision of the document

- -
- - - -
- - - - -
- -
- - -

Create a client for connection to a database -> {ok, db()}

- -
- -
- - - - -
- -
- - -

open a document Params is a list of query argument. Have a look in CouchDb API -> {ok, Doc}|{error, Error}

- -
- - - - - -
- - -

Create a client for connecting to a database and create the database if needed.

- -
- - - -
- - -

put an attachment Body::body(), Option::optionList()) -> {ok, iolist()} optionList() = [option()] option() = {rev, string()} | {content_type, string()} | {content_length, string()} body() = [] | string() | binary() | fun_arity_0() | {fun_arity_1(), initial_state(), stream} initial_state() = term()

- -
- -
- - -

Handle replication. Pass a map containing all information. It allows passing authentication info, etc.

- -
- -
- - -

Handle replication. -> {ok, Result}|{error, Error}

- -
- -
- - -

handle Replication. Allows to pass options with source and target. Source and target can be either simple URI strings or complex document structures with authentication. Options is a Json object. ex

- -
- -
- - -

Equivalent to save_doc(Db, Doc, []).

- -
- -
- - -

save a *document A document is a Json object like this one

- -
- -
- - -

save a *document with all its attacjments A document is a Json object like this one

- -
- -
- - - - -
- -
- - -

save a list of documents

- -
- -
- - -

send an attachment chunk Msg could be Data, eof to stop sending.

- -
- -
- - - - -
- - - - - -
- - -

Create a server for connectiong to a CouchDB node

- -
- -
- - -

Get Information from the server

- -
- -
- - -

fetch an attachment chunk. Use this function when you pass the stream option to the couchbeam:fetch_attachment/4 function. This function return the following response

- -
- -
- - -

stream the multipart response of the doc API. Use this function when you get {ok, {multipart, State}} from the function couchbeam:open_doc/3.

- -
- -
- - -
- -
- -
- - -
-

- - - - Types -

-
-
- -
- - - -
-

db/0

- - - - - - -
-
- -
- -
- -
-type db() :: #db{server :: server(), name :: binary(), options :: list()}.
- -
- - -
-
-
- -
- - - -
-

doc/0

- - - - - - -
-
- -
- -
- -
-type doc() :: ejson_object().
- -
- - -
-
-
- -
- - - -
-

doc_stream/0

- - - - - - -
-
- -
- -
- -
-opaque doc_stream()
- -
- - -
-
-
- -
- - - -
-

ejson_object/0

- - - - - - -
-
- -
- -
- -
-type ejson_object() :: map().
- -
- - -
-
-
- -
- - - -
-

mp_attachment/0

- - - - - - -
-
- -
- -
- -
-type mp_attachment() ::
-          {Name :: binary(), Bin :: binary()} |
-          {Name :: binary(), Bin :: binary(), Encoding :: binary()} |
-          {Name :: binary(), Bin :: binary(), Type :: binary(), Encoding :: binary()} |
-          {Name :: binary(), {file, Path :: string()}} |
-          {Name :: binary(), {file, Path :: string()}, Encoding :: binary()} |
-          {Name :: binary(), Fun :: fun(), Length :: integer()} |
-          {Name :: binary(), Fun :: fun(), Length :: integer(), Encoding :: binary()} |
-          {Name :: binary(), Fun :: fun(), Length :: integer(), Type :: binary(), Encoding :: binary()} |
-          {Name :: binary(), {Fun :: fun(), Acc :: any()}, Length :: integer()} |
-          {Name :: binary(), {Fun :: fun(), Acc :: any()}, Length :: integer(), Encoding :: binary()} |
-          {Name :: binary(),
-           {Fun :: fun(), Acc :: any()},
-           Length :: integer(),
-           Type :: binary(),
-           Encoding :: binary()}.
- -
- - -
-
-
- -
- - - -
-

mp_attachments/0

- - - - - - -
-
- -
- -
- -
-type mp_attachments() :: [mp_attachment()].
- -
- - -
-
-
- -
- - - -
-

server/0

- - - - - - -
-
- -
- -
- -
-type server() :: #server{url :: term(), options :: list()}.
- -
- - -
-
- -
-
- -
-

- - - - Functions -

-
-
- -
- - - -
-

all_dbs(Server)

- - - - - - -
-
- -
- -

get list of databases on a CouchDB node

-
-
-
- -
- - - -
-

all_dbs(Server, Options)

- - - - - - -
-
- -
- -

get list of databases on a CouchDB node with optional filter

-
-
-
- -
- - - -
-

compact(Db)

- - - - - - -
-
- -
- -

Compaction compresses the database file by removing unused sections created during updates. See http://wiki.apache.org/couchdb/Compaction for more informations

-
-
-
- -
- - - -
-

compact(Db, DesignName)

- - - - - - -
-
- -
- -

Like compact/1 but this compacts the view index from the current version of the design document. See http://wiki.apache.org/couchdb/Compaction#View_compaction for more informations

-
-
-
- -
- - - -
-

copy_doc(Db, Doc)

- - - - - - -
-
- -
- -

duplicate a document using the doc API

-
-
-
- -
- - - -
-

copy_doc(Db, Doc, Dest)

- - - - - - -
-
- -
- -

copy a doc to a destination. If the destination exist it will use the last revision, in other case a new doc is created with the the current doc revision.

-
-
-
- -
- - - -
-

create_db(Server, DbName)

- - - - - - -
-
- -
- -

Equivalent to create_db(Server, DbName, [], []).

Create a database and a client for connectiong to it.

-
-
-
- -
- - - -
-

create_db(Server, DbName, Options)

- - - - - - -
-
- -
- -

Equivalent to create_db(Server, DbName, Options, []).

Create a database and a client for connectiong to it.

-
-
-
- -
- - - -
-

create_db(Server, DbName0, Options, Params)

- - - - - - -
-
- -
- -

Create a database and a client for connectiong to it.

Connections are made to:

          http://Host:PortPrefix/DbName

If ssl is set https is used. See server_connections for options. Params is a list of optionnal query argument you want to pass to the db. Useful for bigcouch for example.

Options::optionList(), Params::list()) -> {ok, db()|{error, Error}}

-
-
-
- -
- - - -
-

db_exists(Server, DbName)

- - - - - - -
-
- -
- -

test if db with dbname exists on the CouchDB node

-
-
-
- -
- - - -
-

db_info(Db)

- - - - - - -
-
- -
- -

get database info

-
-
-
- -
- - - -
-

delete_attachment(Db, Doc, Name)

- - - - - - -
-
- -
- -

Equivalent to delete_attachment(Db, Doc, Name, []).

delete a document attachment

-
-
-
- -
- - - -
-

delete_attachment(Db, DocOrDocId, Name, Options)

- - - - - - -
-
- -
- -

delete a document attachment

-
-
-
- -
- - - -
-

delete_db(Db)

- - - - - - -
-
- -
- -

Equivalent to delete_db(Server, DbName).

delete database

-
-
-
- -
- - - -
-

delete_db(Server, DbName)

- - - - - - -
-
- -
- -

delete database

-
-
-
- -
- - - -
-

delete_doc(Db, Doc)

- - - - - - -
-
- -
- -

Equivalent to delete_doc(Db, Doc, []).

delete a document

-
-
-
- -
- - - -
-

delete_doc(Db, Doc, Options)

- - - - - - -
-
- -
- -

delete a document if you want to make sure the doc it emptied on delete, use the option {empty_on_delete, true} or pass a doc with just _id and _rev members.

-
-
-
- -
- - - -
-

delete_docs(Db, Docs)

- - - - - - -
-
- -
- -

Equivalent to delete_docs(Db, Docs, []).

delete a list of documents

-
-
-
- -
- - - -
-

delete_docs(Db, Docs, Options)

- - - - - - -
-
- -
- -

delete a list of documents if you want to make sure the doc it emptied on delete, use the option {empty_on_delete, true} or pass a doc with just _id and _rev members.

-
-
-
- -
- - - -
-

design_info(Db, DesignName)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

doc_exists(Db, DocId)

- - - - - - -
-
- -
- -

test if doc with uuid exists in the given db

-
-
-
- -
- - - -
-

end_doc_stream(_)

- - - - - - -
-
- -
- -
- -
-spec end_doc_stream(doc_stream()) -> ok.
- -
- -

stop to receive the multipart response of the doc api and close the connection.

-
-
-
- -
- - - -
-

ensure_full_commit(Db)

- - - - - - -
-
- -
- -

Equivalent to ensure_full_commit(Db, []).

commit all docs in memory

-
-
-
- -
- - - -
-

ensure_full_commit(Db, Options)

- - - - - - -
-
- -
- -
- -
-spec ensure_full_commit(Db :: db(), Options :: list()) ->
-                            {ok, InstancestartTime :: binary()} | {error, term()}.
- -
- -

commit all docs in memory

-
-
-
- -
- - - -
-

fetch_attachment(Db, DocId, Name)

- - - - - - -
-
- -
- -

Equivalent to fetch_attachment(Db, DocId, Name, []).

fetch a document attachment

-
-
-
- -
- - - -
-

fetch_attachment(Db, DocId, Name, Options0)

- - - - - - -
-
- -
- -
- -
-spec fetch_attachment(db(), list() | binary(), list() | binary(), list()) ->
-                          {ok, binary()} | {ok, atom()} | {error, term()}.
- -
- -

fetch a document attachment Options are

  • stream: to start streaming an attachment. the function return {ok, Ref} where is a ref to the attachment
  • Other options that can be sent using the REST API
-
-
-
- -
- - - -
-

find(Db, Selector, Params)

- - - - - - -
-
- -
- -
- -
-spec find(Db :: db(), Selector :: doc(), Params :: list()) -> {ok, Doc :: doc()} | {error, any()}.
- -
- - -
-
-
- -
- - - -
-

get_missing_revs(Db, IdRevs)

- - - - - - -
-
- -
- -
- -
-spec get_missing_revs(#db{server :: server(), name :: binary(), options :: list()},
-                       [{binary(), [binary()]}]) ->
-                          {ok,
-                           [{DocId :: binary(),
-                             [MissingRev :: binary()],
-                             [PossibleAncestor :: binary()]}]} |
-                          {error, term()}.
- -
- -

get missing revisions

-
-
-
- -
- - - -
-

get_uuid(Server)

- - - - - - -
-
- -
- -

Get one uuid from the server

-
-
-
- -
- - - -
-

get_uuids(Server, Count)

- - - - - - -
-
- -
- -

Get a list of uuids from the server

-
-
-
- -
- - - -
-

lookup_doc_rev(Db, DocId)

- - - - - - -
-
- -
- -

get the last revision of the document

-
-
-
- -
- - - -
-

lookup_doc_rev(Db, DocId, Params)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

open_db(Server, DbName)

- - - - - - -
-
- -
- -

Equivalent to open_db(Server, DbName, []).

Create a client for connection to a database

-
-
-
- -
- - - -
-

open_db(Server, DbName, Options)

- - - - - - -
-
- -
- -

Create a client for connection to a database -> {ok, db()}

-
-
-
- -
- - - -
-

open_doc(Db, DocId)

- - - - - - -
-
- -
- -

Equivalent to open_doc(Db, DocId, []).

open a document

-
-
-
- -
- - - -
-

open_doc(Db, DocId, Params)

- - - - - - -
-
- -
- -

open a document Params is a list of query argument. Have a look in CouchDb API -> {ok, Doc}|{error, Error}

-
-
-
- -
- - - -
-

open_or_create_db(Server, DbName)

- - - - - - -
-
- -
- -

Equivalent to open_or_create_db(Server, DbName, [], []).

Create a client for connecting to a database and create the database if needed.

-
-
-
- -
- - - -
-

open_or_create_db(Server, DbName, Options)

- - - - - - -
-
- -
- -

Equivalent to open_or_create_db(Server, DbName, Options, []).

Create a client for connecting to a database and create the database if needed.

-
-
-
- -
- - - -
-

open_or_create_db(Server, DbName0, Options, Params)

- - - - - - -
-
- -
- -

Create a client for connecting to a database and create the database if needed.

-
-
-
- -
- - - -
-

put_attachment(Db, DocId, Name, Body)

- - - - - - -
-
- -
- -

Equivalent to put_attachment(Db, DocId, Name, Body, []).

put an attachment

-
-
-
- -
- - - -
-

put_attachment(Db, DocId, Name, Body, Options)

- - - - - - -
-
- -
- -

put an attachment Body::body(), Option::optionList()) -> {ok, iolist()} optionList() = [option()] option() = {rev, string()} | {content_type, string()} | {content_length, string()} body() = [] | string() | binary() | fun_arity_0() | {fun_arity_1(), initial_state(), stream} initial_state() = term()

-
-
-
- -
- - - -
-

replicate(Server, RepObj)

- - - - - - -
-
- -
- -

Handle replication. Pass a map containing all information. It allows passing authentication info, etc.

  RepObj = #{
-    <<"source">> => <<"sourcedb">>,
-    <<"target">> => <<"targetdb">>,
-    <<"create_target">> => true
-  }.
-  replicate(Server, RepObj).

-> {ok, Result}|{error, Error}

-
-
-
- -
- - - -
-

replicate(Server, Source, Target)

- - - - - - -
-
- -
- -

Handle replication. -> {ok, Result}|{error, Error}

-
-
-
- -
- - - -
-

replicate(Server, Source, Target, Options)

- - - - - - -
-
- -
- -

handle Replication. Allows to pass options with source and target. Source and target can be either simple URI strings or complex document structures with authentication. Options is a Json object. ex:

  %% Simple URI replication
-  Options = [{<<"create_target">>, true}]},
-  couchbeam:replicate(S, "testdb", "testdb2", Options).
- 
-  %% Complex replication with authentication
-  Source = "http://user:pass@remote.com:5984/db",
-  Target = #{
-    <<"url">> => <<"http://localhost:5984/target_db">>,
-    <<"auth">> => #{
-      <<"basic">> => #{<<"username">> => <<"user">>,
-                       <<"password">> => <<"pass">>}
-    }
-  },
-  couchbeam:replicate(S, Source, Target, [{<<"continuous">>, true}]).
-
-
-
- -
- - - -
-

save_doc(Db, Doc)

- - - - - - -
-
- -
- -

Equivalent to save_doc(Db, Doc, []).

save a document

-
-
-
- -
- - - -
-

save_doc(Db, Doc, Options)

- - - - - - -
-
- -
- -

save a *document A document is a Json object like this one:

          #{
-           <<"_id">> => <<"myid">>,
-           <<"title">> => <<"test">>
-       }

Options are arguments passed to the request. This function return a new document with last revision and a docid. If _id isn't specified in document it will be created. Id is created by extracting an uuid from the couchdb node.

-
-
-
- -
- - - -
-

save_doc(Db, MapDoc, Atts, Options)

- - - - - - -
-
- -
- -
- -
-spec save_doc(Db :: db(), doc(), mp_attachments(), Options :: [{binary(), binary() | true}] | binary()) ->
-                  {ok, doc()} | {error, term()}.
- -
- -

save a *document with all its attacjments A document is a Json object like this one:

          #{
-           <<"_id">> => <<"myid">>,
-           <<"title">> => <<"test">>
-       }

Options are arguments passed to the request. This function return a new document with last revision and a docid. If _id isn't specified in document it will be created. Id is created by extracting an uuid from the couchdb node.

If the attachments is not empty, the doc will be sent as multipart. Attachments are passed as a list of the following tuples:

- {Name :: binary(), Bin :: binary()} - {Name :: binary(), Bin :: binary(), Encoding :: binary()} - { Name :: binary(), Bin :: binary(), Type :: binary(), Encoding :: binary()} - { Name :: binary(), {file, Path :: string()}} - { Name :: binary(), {file, Path :: string()}, Encoding :: binary()} - { Name :: binary(), Fun :: fun(), Length :: integer()} - { Name :: binary(), Fun :: fun(), Length :: integer(), Encoding :: binary()} - {Name :: binary(), Fun :: fun(), Length :: integer(), Type :: binary(), Encoding :: binary()} - { Name :: binary(), {Fun :: fun(), Acc :: any()}, Length :: integer()} - { Name :: binary(), {Fun :: fun(), Acc :: any()}, Length :: integer(), Encoding :: binary()} - { Name :: binary(), {Fun :: fun(), Acc :: any()}, Length :: integer(), Type :: binary(), Encoding :: binary()}.

where Type` is the content-type of the attachments (detected in other case) and `Encoding` the encoding of the attachments: `<<"identity">> if normal or <<"gzip">> if the attachments is gzipped.

-
-
-
- -
- - - -
-

save_docs(Db, Docs)

- - - - - - -
-
- -
- -

Equivalent to save_docs(Db, Docs, []).

save a list of documents

-
-
-
- -
- - - -
-

save_docs(Db, Docs, Options)

- - - - - - -
-
- -
- -

save a list of documents

-
-
-
- -
- - - -
-

send_attachment(Ref, Msg)

- - - - - - -
-
- -
- -

send an attachment chunk Msg could be Data, eof to stop sending.

-
-
-
- -
- - - -
-

server_connection()

- - - - - - -
-
- -
- -

Equivalent to server_connection(URL, Options).

Create a server for connectiong to a CouchDB node

-
-
-
- -
- - - -
-

server_connection(URL)

- - - - - - -
-
- -
- - -
-
-
- -
- - - -
-

server_connection(URL, Options0)

- - - - - - -
-
- -
- -

Equivalent to server_connection(Host, Port, "", []).

Create a server for connectiong to a CouchDB node

-
-
-
- -
- - - -
-

server_connection(Host, Port, Prefix, OptionsList)

- - - - - - -
-
- -
- -
- -
-spec server_connection(Host :: string(),
-                        Port :: non_neg_integer(),
-                        Prefix :: binary(),
-                        OptionsList :: list()) ->
-                           Server :: server().
- -
- -

Create a server for connectiong to a CouchDB node

Connections are made to:

          http://Host:PortPrefix

If ssl is set https is used.

For a description of SSL Options, look in the ssl manpage.

-
-
-
- -
- - - -
-

server_info(Server)

- - - - - - -
-
- -
- -

Get Information from the server

-
-
-
- -
- - - -
-

stream_attachment(Ref)

- - - - - - -
-
- -
- -
- -
-spec stream_attachment(atom()) -> {ok, binary()} | done | {error, term()}.
- -
- -

fetch an attachment chunk. Use this function when you pass the stream option to the couchbeam:fetch_attachment/4 function. This function return the following response:

done
You got all the attachment
{ok, binary()}
Part of the attachment
{error, term()}
n error occurred
-
-
-
- -
- - - -
-

stream_doc(_)

- - - - - - -
-
- -
- -
- -
-spec stream_doc(doc_stream()) ->
-                    {doc, doc()} |
-                    {att, Name :: binary(), doc_stream()} |
-                    {att_body, Name :: binary(), Chunk :: binary(), doc_stream()} |
-                    {att_eof, Name :: binary(), doc_stream()} |
-                    eof |
-                    {error, term()}.
- -
- -

stream the multipart response of the doc API. Use this function when you get {ok, {multipart, State}} from the function couchbeam:open_doc/3.

-
-
-
- -
- - - -
-

view_cleanup(Db)

- - - - - - -
-
- -
- - -
-
- -
-
- - -
-
-
+ + + + + + + +
+
+ + +
+
+

+ couchbeam + (couchbeam v2.0.0) + +

+ + + + View Source + + +
+ + +
+ +
+

+ + + + Summary +

+
+

+ Types +

+ +
+
+ db/0 + +
+ +
+ +
+
+ doc/0 + +
+ +
+ +
+
+ doc_stream/0 + +
+ +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+
+ server/0 + +
+ +
+ +
+
+

+ Functions +

+ +
+ + +

get list of databases on a CouchDB node

+ +
+ +
+ + +

get list of databases on a CouchDB node with optional filter

+ +
+ +
+
+ compact(Db) + +
+ +

Compaction compresses the database file by removing unused sections created during updates. See http://wiki.apache.org/couchdb/Compaction for more informations

+ +
+ +
+ + +

Like compact/1 but this compacts the view index from the current version of the design document. See http://wiki.apache.org/couchdb/Compaction#View_compaction for more informations

+ +
+ +
+ + +

duplicate a document using the doc API

+ +
+ +
+ + +

copy a doc to a destination. If the destination exist it will use the last revision, in other case a new doc is created with the the current doc revision.

+ +
+ + + + + +
+ + +

Create a database and a client for connectiong to it.

+ +
+ +
+ + +

test if db with dbname exists on the CouchDB node

+ +
+ +
+
+ db_info(Db) + +
+ +

get database info

+ +
+ + + +
+ + +

delete a document attachment

+ +
+ +
+ + + + +
+ +
+ + +

delete database

+ +
+ +
+ + + + +
+ +
+ + +

delete a document if you want to make sure the doc it emptied on delete, use the option {empty_on_delete, true} or pass a doc with just _id and _rev members.

+ +
+ +
+ + + + +
+ +
+ + +

delete a list of documents if you want to make sure the doc it emptied on delete, use the option {empty_on_delete, true} or pass a doc with just _id and _rev members.

+ +
+ + + +
+ + +

test if doc with uuid exists in the given db

+ +
+ +
+ + +

stop to receive the multipart response of the doc api and close the connection.

+ +
+ +
+ + + + +
+ +
+ + +

commit all docs in memory

+ +
+ + + +
+ + +

fetch a document attachment Options are

+ +
+ + + +
+ + +

get missing revisions

+ +
+ +
+ + +

Get one uuid from the server

+ +
+ +
+ + +

Get a list of uuids from the server

+ +
+ +
+ + +

get the last revision of the document

+ +
+ + + +
+ + + + +
+ +
+ + +

Create a client for connection to a database -> {ok, db()}

+ +
+ +
+ + + + +
+ +
+ + +

open a document Params is a list of query argument. Have a look in CouchDb API -> {ok, Doc}|{error, Error}

+ +
+ + + + + +
+ + +

Create a client for connecting to a database and create the database if needed.

+ +
+ + + +
+ + +

put an attachment Body::body(), Option::optionList()) -> {ok, iolist()} optionList() = [option()] option() = {rev, string()} | {content_type, string()} | {content_length, string()} body() = [] | string() | binary() | fun_arity_0() | {fun_arity_1(), initial_state(), stream} initial_state() = term()

+ +
+ +
+ + +

Handle replication. Pass a map containing all information. It allows passing authentication info, etc.

+ +
+ +
+ + +

Handle replication. -> {ok, Result}|{error, Error}

+ +
+ +
+ + +

handle Replication. Allows to pass options with source and target. Source and target can be either simple URI strings or complex document structures with authentication. Options is a Json object. ex

+ +
+ +
+ + +

Equivalent to save_doc(Db, Doc, []).

+ +
+ +
+ + +

save a *document A document is a Json object like this one

+ +
+ +
+ + +

save a *document with all its attacjments A document is a Json object like this one

+ +
+ +
+ + + + +
+ +
+ + +

save a list of documents

+ +
+ +
+ + +

send an attachment chunk Msg could be Data, eof to stop sending.

+ +
+ +
+ + + + +
+ + + + + +
+ + +

Create a server for connectiong to a CouchDB node

+ +
+ +
+ + +

Get Information from the server

+ +
+ +
+ + +

fetch an attachment chunk. Use this function when you pass the stream option to the couchbeam:fetch_attachment/4 function. This function return the following response

+ +
+ +
+ + +

stream the multipart response of the doc API. Use this function when you get {ok, {multipart, State}} from the function couchbeam:open_doc/3.

+ +
+ +
+ + +
+ +
+ +
+ + +
+

+ + + + Types +

+
+
+ +
+ + + +
+

db/0

+ + + + + + +
+
+ +
+ +
+ +
-type db() :: #db{server :: server(), name :: binary(), options :: list()}.
+ +
+ + +
+
+
+ +
+ + + +
+

doc/0

+ + + + + + +
+
+ +
+ +
+ +
-type doc() :: ejson_object().
+ +
+ + +
+
+
+ +
+ + + +
+

doc_stream/0

+ + + + + + +
+
+ +
+ +
+ +
-opaque doc_stream()
+ +
+ + +
+
+
+ +
+ + + +
+

ejson_object/0

+ + + + + + +
+
+ +
+ +
+ +
-type ejson_object() :: map().
+ +
+ + +
+
+
+ +
+ + + +
+

mp_attachment/0

+ + + + + + +
+
+ +
+ +
+ +
-type mp_attachment() ::
+          {Name :: binary(), Bin :: binary()} |
+          {Name :: binary(), Bin :: binary(), Encoding :: binary()} |
+          {Name :: binary(), Bin :: binary(), Type :: binary(), Encoding :: binary()} |
+          {Name :: binary(), {file, Path :: string()}} |
+          {Name :: binary(), {file, Path :: string()}, Encoding :: binary()} |
+          {Name :: binary(), Fun :: fun(), Length :: integer()} |
+          {Name :: binary(), Fun :: fun(), Length :: integer(), Encoding :: binary()} |
+          {Name :: binary(), Fun :: fun(), Length :: integer(), Type :: binary(), Encoding :: binary()} |
+          {Name :: binary(), {Fun :: fun(), Acc :: any()}, Length :: integer()} |
+          {Name :: binary(), {Fun :: fun(), Acc :: any()}, Length :: integer(), Encoding :: binary()} |
+          {Name :: binary(),
+           {Fun :: fun(), Acc :: any()},
+           Length :: integer(),
+           Type :: binary(),
+           Encoding :: binary()}.
+ +
+ + +
+
+
+ +
+ + + +
+

mp_attachments/0

+ + + + + + +
+
+ +
+ +
+ +
-type mp_attachments() :: [mp_attachment()].
+ +
+ + +
+
+
+ +
+ + + +
+

server/0

+ + + + + + +
+
+ +
+ +
+ +
-type server() :: #server{url :: term(), options :: list()}.
+ +
+ + +
+
+ +
+
+ +
+

+ + + + Functions +

+
+
+ +
+ + + +
+

all_dbs(Server)

+ + + + + + +
+
+ +
+ +

get list of databases on a CouchDB node

+
+
+
+ +
+ + + +
+

all_dbs(Server, Options)

+ + + + + + +
+
+ +
+ +

get list of databases on a CouchDB node with optional filter

+
+
+
+ +
+ + + +
+

compact(Db)

+ + + + + + +
+
+ +
+ +

Compaction compresses the database file by removing unused sections created during updates. See http://wiki.apache.org/couchdb/Compaction for more informations

+
+
+
+ +
+ + + +
+

compact(Db, DesignName)

+ + + + + + +
+
+ +
+ +

Like compact/1 but this compacts the view index from the current version of the design document. See http://wiki.apache.org/couchdb/Compaction#View_compaction for more informations

+
+
+
+ +
+ + + +
+

copy_doc(Db, Doc)

+ + + + + + +
+
+ +
+ +

duplicate a document using the doc API

+
+
+
+ +
+ + + +
+

copy_doc(Db, Doc, Dest)

+ + + + + + +
+
+ +
+ +

copy a doc to a destination. If the destination exist it will use the last revision, in other case a new doc is created with the the current doc revision.

+
+
+
+ +
+ + + +
+

create_db(Server, DbName)

+ + + + + + +
+
+ +
+ +

Equivalent to create_db(Server, DbName, [], []).

Create a database and a client for connectiong to it.

+
+
+
+ +
+ + + +
+

create_db(Server, DbName, Options)

+ + + + + + +
+
+ +
+ +

Equivalent to create_db(Server, DbName, Options, []).

Create a database and a client for connectiong to it.

+
+
+
+ +
+ + + +
+

create_db(Server, DbName0, Options, Params)

+ + + + + + +
+
+ +
+ +

Create a database and a client for connectiong to it.

Connections are made to:

          http://Host:PortPrefix/DbName

If ssl is set https is used. See server_connections for options. Params is a list of optionnal query argument you want to pass to the db. Useful for bigcouch for example.

Options::optionList(), Params::list()) -> {ok, db()|{error, Error}}

+
+
+
+ +
+ + + +
+

db_exists(Server, DbName)

+ + + + + + +
+
+ +
+ +

test if db with dbname exists on the CouchDB node

+
+
+
+ +
+ + + +
+

db_info(Db)

+ + + + + + +
+
+ +
+ +

get database info

+
+
+
+ +
+ + + +
+

delete_attachment(Db, Doc, Name)

+ + + + + + +
+
+ +
+ +

Equivalent to delete_attachment(Db, Doc, Name, []).

delete a document attachment

+
+
+
+ +
+ + + +
+

delete_attachment(Db, DocOrDocId, Name, Options)

+ + + + + + +
+
+ +
+ +

delete a document attachment

+
+
+
+ +
+ + + +
+

delete_db(Db)

+ + + + + + +
+
+ +
+ +

Equivalent to delete_db(Server, DbName).

delete database

+
+
+
+ +
+ + + +
+

delete_db(Server, DbName)

+ + + + + + +
+
+ +
+ +

delete database

+
+
+
+ +
+ + + +
+

delete_doc(Db, Doc)

+ + + + + + +
+
+ +
+ +

Equivalent to delete_doc(Db, Doc, []).

delete a document

+
+
+
+ +
+ + + +
+

delete_doc(Db, Doc, Options)

+ + + + + + +
+
+ +
+ +

delete a document if you want to make sure the doc it emptied on delete, use the option {empty_on_delete, true} or pass a doc with just _id and _rev members.

+
+
+
+ +
+ + + +
+

delete_docs(Db, Docs)

+ + + + + + +
+
+ +
+ +

Equivalent to delete_docs(Db, Docs, []).

delete a list of documents

+
+
+
+ +
+ + + +
+

delete_docs(Db, Docs, Options)

+ + + + + + +
+
+ +
+ +

delete a list of documents if you want to make sure the doc it emptied on delete, use the option {empty_on_delete, true} or pass a doc with just _id and _rev members.

+
+
+
+ +
+ + + +
+

design_info(Db, DesignName)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

doc_exists(Db, DocId)

+ + + + + + +
+
+ +
+ +

test if doc with uuid exists in the given db

+
+
+
+ +
+ + + +
+

end_doc_stream(_)

+ + + + + + +
+
+ +
+ +
+ +
-spec end_doc_stream(doc_stream()) -> ok.
+ +
+ +

stop to receive the multipart response of the doc api and close the connection.

+
+
+
+ +
+ + + +
+

ensure_full_commit(Db)

+ + + + + + +
+
+ +
+ +

Equivalent to ensure_full_commit(Db, []).

commit all docs in memory

+
+
+
+ +
+ + + +
+

ensure_full_commit(Db, Options)

+ + + + + + +
+
+ +
+ +
+ +
-spec ensure_full_commit(Db :: db(), Options :: list()) ->
+                            {ok, InstancestartTime :: binary()} | {error, term()}.
+ +
+ +

commit all docs in memory

+
+
+
+ +
+ + + +
+

fetch_attachment(Db, DocId, Name)

+ + + + + + +
+
+ +
+ +

Equivalent to fetch_attachment(Db, DocId, Name, []).

fetch a document attachment

+
+
+
+ +
+ + + +
+

fetch_attachment(Db, DocId, Name, Options0)

+ + + + + + +
+
+ +
+ +
+ +
-spec fetch_attachment(db(), list() | binary(), list() | binary(), list()) ->
+                          {ok, binary()} | {ok, atom()} | {error, term()}.
+ +
+ +

fetch a document attachment Options are

  • stream: to start streaming an attachment. the function return {ok, Ref} where is a ref to the attachment
  • Other options that can be sent using the REST API
+
+
+
+ +
+ + + +
+

find(Db, Selector, Params)

+ + + + + + +
+
+ +
+ +
+ +
-spec find(Db :: db(), Selector :: doc(), Params :: list()) -> {ok, Doc :: doc()} | {error, any()}.
+ +
+ + +
+
+
+ +
+ + + +
+

get_missing_revs(Db, IdRevs)

+ + + + + + +
+
+ +
+ +
+ +
-spec get_missing_revs(#db{server :: server(), name :: binary(), options :: list()},
+                       [{binary(), [binary()]}]) ->
+                          {ok,
+                           [{DocId :: binary(),
+                             [MissingRev :: binary()],
+                             [PossibleAncestor :: binary()]}]} |
+                          {error, term()}.
+ +
+ +

get missing revisions

+
+
+
+ +
+ + + +
+

get_uuid(Server)

+ + + + + + +
+
+ +
+ +

Get one uuid from the server

+
+
+
+ +
+ + + +
+

get_uuids(Server, Count)

+ + + + + + +
+
+ +
+ +

Get a list of uuids from the server

+
+
+
+ +
+ + + +
+

lookup_doc_rev(Db, DocId)

+ + + + + + +
+
+ +
+ +

get the last revision of the document

+
+
+
+ +
+ + + +
+

lookup_doc_rev(Db, DocId, Params)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

open_db(Server, DbName)

+ + + + + + +
+
+ +
+ +

Equivalent to open_db(Server, DbName, []).

Create a client for connection to a database

+
+
+
+ +
+ + + +
+

open_db(Server, DbName, Options)

+ + + + + + +
+
+ +
+ +

Create a client for connection to a database -> {ok, db()}

+
+
+
+ +
+ + + +
+

open_doc(Db, DocId)

+ + + + + + +
+
+ +
+ +

Equivalent to open_doc(Db, DocId, []).

open a document

+
+
+
+ +
+ + + +
+

open_doc(Db, DocId, Params)

+ + + + + + +
+
+ +
+ +

open a document Params is a list of query argument. Have a look in CouchDb API -> {ok, Doc}|{error, Error}

+
+
+
+ +
+ + + +
+

open_or_create_db(Server, DbName)

+ + + + + + +
+
+ +
+ +

Equivalent to open_or_create_db(Server, DbName, [], []).

Create a client for connecting to a database and create the database if needed.

+
+
+
+ +
+ + + +
+

open_or_create_db(Server, DbName, Options)

+ + + + + + +
+
+ +
+ +

Equivalent to open_or_create_db(Server, DbName, Options, []).

Create a client for connecting to a database and create the database if needed.

+
+
+
+ +
+ + + +
+

open_or_create_db(Server, DbName0, Options, Params)

+ + + + + + +
+
+ +
+ +

Create a client for connecting to a database and create the database if needed.

+
+
+
+ +
+ + + +
+

put_attachment(Db, DocId, Name, Body)

+ + + + + + +
+
+ +
+ +

Equivalent to put_attachment(Db, DocId, Name, Body, []).

put an attachment

+
+
+
+ +
+ + + +
+

put_attachment(Db, DocId, Name, Body, Options)

+ + + + + + +
+
+ +
+ +

put an attachment Body::body(), Option::optionList()) -> {ok, iolist()} optionList() = [option()] option() = {rev, string()} | {content_type, string()} | {content_length, string()} body() = [] | string() | binary() | fun_arity_0() | {fun_arity_1(), initial_state(), stream} initial_state() = term()

+
+
+
+ +
+ + + +
+

replicate(Server, RepObj)

+ + + + + + +
+
+ +
+ +

Handle replication. Pass a map containing all information. It allows passing authentication info, etc.

  RepObj = #{
+    <<"source">> => <<"sourcedb">>,
+    <<"target">> => <<"targetdb">>,
+    <<"create_target">> => true
+  }.
+  replicate(Server, RepObj).

-> {ok, Result}|{error, Error}

+
+
+
+ +
+ + + +
+

replicate(Server, Source, Target)

+ + + + + + +
+
+ +
+ +

Handle replication. -> {ok, Result}|{error, Error}

+
+
+
+ +
+ + + +
+

replicate(Server, Source, Target, Options)

+ + + + + + +
+
+ +
+ +

handle Replication. Allows to pass options with source and target. Source and target can be either simple URI strings or complex document structures with authentication. Options is a Json object. ex:

  %% Simple URI replication
+  Options = [{<<"create_target">>, true}]},
+  couchbeam:replicate(S, "testdb", "testdb2", Options).
+ 
+  %% Complex replication with authentication
+  Source = "http://user:pass@remote.com:5984/db",
+  Target = #{
+    <<"url">> => <<"http://localhost:5984/target_db">>,
+    <<"auth">> => #{
+      <<"basic">> => #{<<"username">> => <<"user">>,
+                       <<"password">> => <<"pass">>}
+    }
+  },
+  couchbeam:replicate(S, Source, Target, [{<<"continuous">>, true}]).
+
+
+
+ +
+ + + +
+

save_doc(Db, Doc)

+ + + + + + +
+
+ +
+ +

Equivalent to save_doc(Db, Doc, []).

save a document

+
+
+
+ +
+ + + +
+

save_doc(Db, Doc, Options)

+ + + + + + +
+
+ +
+ +

save a *document A document is a Json object like this one:

          #{
+           <<"_id">> => <<"myid">>,
+           <<"title">> => <<"test">>
+       }

Options are arguments passed to the request. This function return a new document with last revision and a docid. If _id isn't specified in document it will be created. Id is created by extracting an uuid from the couchdb node.

+
+
+
+ +
+ + + +
+

save_doc(Db, MapDoc, Atts, Options)

+ + + + + + +
+
+ +
+ +
+ +
-spec save_doc(Db :: db(), doc(), mp_attachments(), Options :: [{binary(), binary() | true}] | binary()) ->
+                  {ok, doc()} | {error, term()}.
+ +
+ +

save a *document with all its attacjments A document is a Json object like this one:

          #{
+           <<"_id">> => <<"myid">>,
+           <<"title">> => <<"test">>
+       }

Options are arguments passed to the request. This function return a new document with last revision and a docid. If _id isn't specified in document it will be created. Id is created by extracting an uuid from the couchdb node.

If the attachments is not empty, the doc will be sent as multipart. Attachments are passed as a list of the following tuples:

- {Name :: binary(), Bin :: binary()} - {Name :: binary(), Bin :: binary(), Encoding :: binary()} - { Name :: binary(), Bin :: binary(), Type :: binary(), Encoding :: binary()} - { Name :: binary(), {file, Path :: string()}} - { Name :: binary(), {file, Path :: string()}, Encoding :: binary()} - { Name :: binary(), Fun :: fun(), Length :: integer()} - { Name :: binary(), Fun :: fun(), Length :: integer(), Encoding :: binary()} - {Name :: binary(), Fun :: fun(), Length :: integer(), Type :: binary(), Encoding :: binary()} - { Name :: binary(), {Fun :: fun(), Acc :: any()}, Length :: integer()} - { Name :: binary(), {Fun :: fun(), Acc :: any()}, Length :: integer(), Encoding :: binary()} - { Name :: binary(), {Fun :: fun(), Acc :: any()}, Length :: integer(), Type :: binary(), Encoding :: binary()}.

where Type` is the content-type of the attachments (detected in other case) and `Encoding` the encoding of the attachments: `<<"identity">> if normal or <<"gzip">> if the attachments is gzipped.

+
+
+
+ +
+ + + +
+

save_docs(Db, Docs)

+ + + + + + +
+
+ +
+ +

Equivalent to save_docs(Db, Docs, []).

save a list of documents

+
+
+
+ +
+ + + +
+

save_docs(Db, Docs, Options)

+ + + + + + +
+
+ +
+ +

save a list of documents

+
+
+
+ +
+ + + +
+

send_attachment(Ref, Msg)

+ + + + + + +
+
+ +
+ +

send an attachment chunk Msg could be Data, eof to stop sending.

+
+
+
+ +
+ + + +
+

server_connection()

+ + + + + + +
+
+ +
+ +

Equivalent to server_connection(URL, Options).

Create a server for connectiong to a CouchDB node

+
+
+
+ +
+ + + +
+

server_connection(URL)

+ + + + + + +
+
+ +
+ + +
+
+
+ +
+ + + +
+

server_connection(URL, Options0)

+ + + + + + +
+
+ +
+ +

Equivalent to server_connection(Host, Port, "", []).

Create a server for connectiong to a CouchDB node

+
+
+
+ +
+ + + +
+

server_connection(Host, Port, Prefix, OptionsList)

+ + + + + + +
+
+ +
+ +
+ +
-spec server_connection(Host :: string(),
+                        Port :: non_neg_integer(),
+                        Prefix :: binary(),
+                        OptionsList :: list()) ->
+                           Server :: server().
+ +
+ +

Create a server for connectiong to a CouchDB node

Connections are made to:

          http://Host:PortPrefix

If ssl is set https is used.

For a description of SSL Options, look in the ssl manpage.

+
+
+
+ +
+ + + +
+

server_info(Server)

+ + + + + + +
+
+ +
+ +

Get Information from the server

+
+
+
+ +
+ + + +
+

stream_attachment(Ref)

+ + + + + + +
+
+ +
+ +
+ +
-spec stream_attachment(atom()) -> {ok, binary()} | done | {error, term()}.
+ +
+ +

fetch an attachment chunk. Use this function when you pass the stream option to the couchbeam:fetch_attachment/4 function. This function return the following response:

done
You got all the attachment
{ok, binary()}
Part of the attachment
{error, term()}
n error occurred
+
+
+
+ +
+ + + +
+

stream_doc(_)

+ + + + + + +
+
+ +
+ +
+ +
-spec stream_doc(doc_stream()) ->
+                    {doc, doc()} |
+                    {att, Name :: binary(), doc_stream()} |
+                    {att_body, Name :: binary(), Chunk :: binary(), doc_stream()} |
+                    {att_eof, Name :: binary(), doc_stream()} |
+                    eof |
+                    {error, term()}.
+ +
+ +

stream the multipart response of the doc API. Use this function when you get {ok, {multipart, State}} from the function couchbeam:open_doc/3.

+
+
+
+ +
+ + + +
+

view_cleanup(Db)

+ + + + + + +
+
+ +
+ + +
+
+ +
+
+ + +
+
+