Repository: barrel-db/barrel-platform Branch: master Commit: f55fdb311d1b Files: 104 Total size: 3.1 MB Directory structure: gitextract_vdj5mcu_/ ├── .codeclimate.yml ├── .dir-locals.el ├── .eqc_ci ├── .github/ │ ├── ISSUE_TEMPLATE.md │ └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .gitlab/ │ └── issue_templates/ │ └── Bug.md ├── EQC_CI_LICENCE.txt ├── HowToRunQuickCheck.md ├── LICENSE ├── Makefile ├── README.md ├── apps/ │ ├── barrel_ctl/ │ │ └── src/ │ │ ├── barrel_ctl.app.src │ │ └── barrel_ctl.erl │ ├── barrel_httpc/ │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── README.md │ │ ├── rebar.config │ │ ├── src/ │ │ │ ├── barrel_httpc.app.src │ │ │ ├── barrel_httpc.erl │ │ │ ├── barrel_httpc_app.erl │ │ │ ├── barrel_httpc_attachments.erl │ │ │ ├── barrel_httpc_changes.erl │ │ │ ├── barrel_httpc_fold.erl │ │ │ ├── barrel_httpc_lib.erl │ │ │ ├── barrel_httpc_sup.erl │ │ │ └── barrel_jsonpointer.erl │ │ └── test/ │ │ ├── barrel_httpc_attachments_SUITE.erl │ │ ├── barrel_httpc_changes_test_SUITE.erl │ │ └── barrel_httpc_test_SUITE.erl │ └── barrel_rest/ │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── priv/ │ │ └── swagger/ │ │ ├── css/ │ │ │ ├── print.css │ │ │ ├── reset.css │ │ │ ├── screen.css │ │ │ ├── style.css │ │ │ └── typography.css │ │ ├── index.html │ │ ├── lang/ │ │ │ ├── ca.js │ │ │ ├── el.js │ │ │ ├── en.js │ │ │ ├── es.js │ │ │ ├── fr.js │ │ │ ├── geo.js │ │ │ ├── it.js │ │ │ ├── ja.js │ │ │ ├── ko-kr.js │ │ │ ├── pl.js │ │ │ ├── pt.js │ │ │ ├── ru.js │ │ │ ├── tr.js │ │ │ ├── translator.js │ │ │ └── zh-cn.js │ │ ├── lib/ │ │ │ ├── backbone-min.js │ │ │ ├── es5-shim.js │ │ │ ├── handlebars-4.0.5.js │ │ │ ├── highlight.9.1.0.pack.js │ │ │ ├── highlight.9.1.0.pack_extended.js │ │ │ ├── marked.js │ │ │ ├── object-assign-pollyfill.js │ │ │ └── swagger-oauth.js │ │ ├── o2c.html │ │ ├── swagger-ui.js │ │ └── swagger.yaml │ ├── rebar.config │ ├── src/ │ │ ├── barrel_http_count.erl │ │ ├── barrel_http_lib.erl │ │ ├── barrel_http_redirect.erl │ │ ├── barrel_http_reply.erl │ │ ├── barrel_http_rest_db.erl │ │ ├── barrel_http_rest_dbs.erl │ │ ├── barrel_http_rest_docs.erl │ │ ├── barrel_http_rest_docs.hrl │ │ ├── barrel_http_rest_docs_changes.erl │ │ ├── barrel_http_rest_docs_id.erl │ │ ├── barrel_http_rest_docs_list.erl │ │ ├── barrel_http_rest_replicate.erl │ │ ├── barrel_http_rest_revsdiff.erl │ │ ├── barrel_http_rest_root.erl │ │ ├── barrel_http_rest_system.erl │ │ ├── barrel_http_rest_walk.erl │ │ ├── barrel_rest.app.src │ │ ├── barrel_rest_app.erl │ │ ├── barrel_rest_ids.erl │ │ └── barrel_rest_sup.erl │ └── test/ │ ├── barrel_rest_all_docs_SUITE.erl │ ├── barrel_rest_changes_SUITE.erl │ ├── barrel_rest_dbs_SUITE.erl │ ├── barrel_rest_doc_SUITE.erl │ ├── barrel_rest_ids_SUITE.erl │ ├── barrel_rest_replicate_SUITE.erl │ ├── barrel_rest_system_SUITE.erl │ └── test_lib.erl ├── bin/ │ └── barrel_ctl.sh ├── config/ │ ├── sys.config │ └── vm.args ├── rebar.config └── support/ ├── import.sh ├── qa/ │ ├── README.md │ ├── helpchange.erl │ └── helpreplicate.erl ├── rebar3 └── remove_deps.escript ================================================ FILE CONTENTS ================================================ ================================================ FILE: .codeclimate.yml ================================================ exclude_paths: - "apps/barrel_http/priv/swagger/" ================================================ FILE: .dir-locals.el ================================================ ;; This file will set emacs to use tabwidth of 2 for this project ;; ((nil . ((indent-tabs-mode . t) (tab-width . 2)))) ================================================ FILE: .eqc_ci ================================================ %-*-Erlang-*- {build, "make eqc"}. ================================================ FILE: .github/ISSUE_TEMPLATE.md ================================================ (REPLACE ALL UPPERCASE EXPRESSIONS AND DELETE THIS LINE TO SUBMIT) #### Description :octocat: (DESCRIPTION OF THE PROBLEM) #### Reproduction guide :beetle: - Start Barrel - (REPRODUCTION STEPS) *Observed behaviour:* :eyes: :broken_heart: (DESCRIPTION OF THE OBSERVED BEHAVIOUR) *Expected behaviour:* :heart: :smile: (DESCRIPTION OF THE EXPECTED BEHAVIOUR) #### Backtrace :paw_prints: ‡ ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ Thank you for contributing to Barrel! Before you submit this pull request, please ensure it is against the develop branch and not master. This message should be replaced with a description of your change. Thank you <3 ================================================ FILE: .gitignore ================================================ .rebar3 _* .eunit *.o *.beam *.plt *.swp *.swo .idea .erlang.cookie ebin log erl_crash.dump .rebar log logs _build docs data *.iml .gitlab-ci.yml barrel_platform_*_plt rebar3.crashdump *~ eqc .eqc-info Compiling current_counterexample.eqc .vagrant rebar.lock ================================================ FILE: .gitlab/issue_templates/Bug.md ================================================ We’re closing our issue tracker on Gitlab so we can focus on the [Github.com](https://github.com/barrel-db/barrel-platform) project and respond to issues more quickly. We encourage you to open an issue on the Github.com issue tracker. ================================================ FILE: EQC_CI_LICENCE.txt ================================================ This file is an agreement between Quviq AB ("Quviq"), Sven Hultins Gata 9, Gothenburg, Sweden, and the committers to the github repository in which the file appears ("the owner"). By placing this file in a github repository, the owner agrees to the terms below. The purpose of the agreement is to enable Quviq AB to provide a continuous integration service to the owner, whereby the code in the repository ("the source code") is tested using Quviq's test tools, and the test results are made available on the web. The test results include test output, generated test cases, and a copy of the source code in the repository annotated with coverage information ("the test results"). The owner agrees that Quviq may run the tests in the source code and display the test results on the web, without obligation. The owner warrants that running the tests in the source code and displaying the test results on the web violates no laws, licences or other agreements. In the event of such a violation, the owner accepts full responsibility. The owner warrants that the source code is not malicious, and will not mount an attack on either Quviq's server or any other server--for example by taking part in a denial of service attack, or by attempting to send unsolicited emails. The owner warrants that the source code does not attempt to reverse engineer Quviq's code. Quviq reserves the right to exclude repositories that break this agreement from its continuous integration service. Any dispute arising from the use of Quviq's service will be resolved under Swedish law. ================================================ FILE: HowToRunQuickCheck.md ================================================ # How to run QuickCheck In order to run QuickCheck you will need a license and to install QuickCheck. ## To Install QuickCheck Download QuickCheck from http://quviq-licencer.com/downloads/eqc.zip Unzip the file and CD Into the directory as Root ``` erl > eqc:install(). ``` ## Install your licence As your user in Erlang ``` > eqc:registration("LICENCE ID"). ``` ## Running Properties QuickCheck properties are in application directories `eqc`. There is a `user_default.erl` file that has a few useful commands in it. To run the QuickCheck properties from the Erlang shell type the command `eqc()`. ## Running properties with Rebar3 run `rebar3 eqc` (Not yet working) ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: Makefile ================================================ BASEDIR = $(shell pwd) SUPPORTDIR = $(BASEDIR)/support REBAR ?= $(SUPPORTDIR)/rebar3 OTP_VERSION?=19.3 BUILD_NAME?=dirty-1 KERL_DEFAULT_INSTALL_DIR?=$(HOME)/.kerl/local/$(BUILD_NAME)/otp KERL_CONFIGURE_OPTIONS?=" --disable-hipe --enable-smp-support --enable-threads --enable-kernel-poll --with-wx --without-odbc --enable-dirty-schedulers" .PHONY: help all rel tar store apply eqc all: compile compile: @$(REBAR) compile ## Create a barrel release rel: @$(REBAR) as prod release devrel: ## Create a barrel release @$(REBAR) release tar: ## Create a tar file containing a portable release @$(REBAR) as prod tar clean: @$(REBAR) clean distclean: clean ## Clean all build and releases artifacts rm -rf _build cleantest: @rm -rf _build/test erlclean: kerl delete build $(BUILD_NAME) build_erlang: KERL_CONFIGURE_OPTIONS=$(KERL_CONFIGURE_OPTIONS) \ KERL_DEFAULT_INSTALL_DIR=$(KERL_DEFAULT_INSTALL_DIR) \ kerl build $(OTP_VERSION) $(BUILD_NAME) install_erlang: build_erlang kerl install $(BUILD_NAME) $(KERL_DEFAULT_INSTALL_DIR) . $(KERL_DEFAULT_INSTALL_DIR)/activate shell: @$(REBAR) shell --sname barrel@localhost activate: . $(KERL_DEFAULT_INSTALL_DIR)/activate dialyzer: @$(REBAR) dialyzer test: cleantest dialyzer eunit ct eunit: @$(REBAR) eunit ct: @$(REBAR) ct eqc: @$(REBAR) as eqc eqc cover: @$(REBAR) cover help: ## This documentation @echo Build commands for barrel platform: @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | \ awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' @echo @echo Default command is \'compile\' @echo Consult README.md for more information. ================================================ FILE: README.md ================================================

build status

A document-oriented database targeting data locality & P2P - barrel-db.org

# Barrel platform Barrel is a modern document-oriented database in Erlang focusing on data locality (put/match the data next to you) and P2P. Barrel must also be able to work in unreliable conditions were sometimes the quorum can't be achieved (because it is working offline or in other conditions). Because Barrel is built on an existing relatively small code base, it is possible to make radical changes as part of an incremental process. Underpinning, all this work is efficient for small and large data systems — something rare among database systems. ## Requirements - OS supported: Linux, OSX, BSDs - Erlang 19.2 ## Prerequisites This repository contains an [Erlang](https://www.erlang.org/) project packaged with [rebar3](https://www.rebar3.org/). You need to have Erlang 19.1 and the latest version of [rebar3](http://rebar3.org) installed to be able to create a release. ## Quickstart $ make rel $ ./_build/default/rel/barrel/bin/barrel start ## Building a release Execute the following command line: $ make rel The generated release can be found in the folder `_build/prod/rel` . > to build a development release, run the command line `make devrel` . > Please note that this release can't be shipped outside of the current project, > the release will be found in the folder `_build/default/rel`. ## Testing a release To start a barrel http server: $ ./_build/prod/rel/barrel/bin/barrel start To stop it: $ ./_build/prod/rel/barrel/bin/barrel stop List of available commands: $ ./_build/prod/rel/barrel/bin/barrel You can consult the embedded [Swagger](http://swagger.io/) page at http://localhost:7080/api-docs ## Packaging an autonomous tar file This command create a tarbal including barrek, erlang and associated libs: $ make tar You can deploy the tarball wherever you want: $ mkdir barrelprod $ cd barrelprod $ tar -xzf ../barrel-0.1.0.tar.gz $ bin/barrel_http start ================================================ FILE: apps/barrel_ctl/src/barrel_ctl.app.src ================================================ {application, barrel_ctl, [{description, "An OTP library"}, {vsn, "0.1.0"}, {registered, []}, {applications, [kernel, stdlib ]}, {env,[]}, {modules, []}, {maintainers, []}, {licenses, ["Apache 2.0"]}, {links, []} ]}. ================================================ FILE: apps/barrel_ctl/src/barrel_ctl.erl ================================================ -module(barrel_ctl). %% API exports -export([ new_snapshot/1, restore_from_snapshot/1 ]). new_snapshot([DbName, Path]) -> case filelib:is_dir(Path) of true -> io:format("ERROR: ~p already exists.~n", [Path]), error; false -> case barrel_backup:new_snapshot(list_to_binary(DbName), Path) of ok -> io:format("SUCCESS: ~p snapshot created at ~p~n", [DbName, Path]), ok; {error, Reason} -> io:format("ERROR: ~p.~n", [Reason]), error end end; new_snapshot(_) -> io:format("ERROR: invalid arguments.~n", []), error. restore_from_snapshot([DbName, Path]) -> case barrel_backup:restore_from_snapshot(list_to_binary(DbName), Path) of {ok, OldPath} -> io:format("SUCCESS: ~s", [OldPath]), ok; {error, Reason} -> io:format("ERROR: ~p.~n", [Reason]), error end; restore_from_snapshot(_) -> io:format("ERROR: invalid arguments.~n", []), error. ================================================ FILE: apps/barrel_httpc/.gitignore ================================================ .rebar3 _* .eunit *.o *.beam *.plt *.swp *.swo .erlang.cookie ebin log erl_crash.dump .rebar logs _build .idea rebar3.crashdump ================================================ FILE: apps/barrel_httpc/LICENSE ================================================ Copyright (c) 2017, Benoit Chesneau . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: apps/barrel_httpc/README.md ================================================ barrel_httpc ===== An OTP application Build ----- $ rebar3 compile ================================================ FILE: apps/barrel_httpc/rebar.config ================================================ {erl_opts, [debug_info]}. {deps, [ ]}. ================================================ FILE: apps/barrel_httpc/src/barrel_httpc.app.src ================================================ {application, barrel_httpc, [{description, "An OTP application"}, {vsn, "0.1.0"}, {registered, []}, {mod, { barrel_httpc_app, []}}, {applications, [kernel, stdlib, sasl, lager, crypto, hackney ]}, {env,[]}, {modules, []}, {maintainers, []}, {licenses, []}, {links, []} ]}. ================================================ FILE: apps/barrel_httpc/src/barrel_httpc.erl ================================================ %%%------------------------------------------------------------------- %%% @author benoitc %%% @copyright (C) 2017, %%% @doc %%% %%% @end %%% Created : 17. Jan 2017 12:35 %%%------------------------------------------------------------------- -module(barrel_httpc). -author("benoitc"). %% API -export([ create_database/1, create_database/2, delete_database/1, database_names/1, database_infos/1, connect/1, get/3, multi_get/5, put/3, put/4, post/3, post/4, delete/3, update_with/4, put_rev/5, write_batch/3, fold_by_id/4, fold_by_path/5, changes_since/5, revsdiff/2, revsdiff/3 ]). -export([ attach/4, attach/5, get_attachment/4, get_attachment_binary/4, replace_attachment/5, replace_attachment_binary/5, delete_attachment/4, attachments/3 ]). -export([ get_system_doc/2, put_system_doc/3, delete_system_doc/2 ]). -export([ start_changes_listener/2, stop_changes_listener/1, get_changes/1 ]). -include_lib("hackney/include/hackney_lib.hrl"). -type conn() :: term(). -type docid() :: binary(). -type rev() :: binary(). -type revid() :: binary(). -type revinfo() :: #{ id := revid(), parent := revid(), deleted => boolean() }. -type revtree() :: #{ revid() => revinfo() }. -type read_option() :: rev() | {history, true | false}. -type write_options() :: list(). -type db_infos() :: map(). -type doc() :: map(). -type meta() :: map(). -type read_options() :: [read_option()]. %% TODO: to define -type fold_options() :: list(). -type change() :: #{ binary() => any() }. -type attachment() :: #{binary() => any()}. -type attid() :: binary(). -type att_description() :: map(). -type batch_options() :: [ {async, boolean()} ]. -type batch_results() :: [ {ok, docid(), revid()} | {error, not_found} | {error, {conflict, doc_exists}} | {error, {conflict, revision_conflict}} | {error, any()} ]. -type batch_op() :: {put, Doc :: barrel:doc()} | {put, Doc :: barrel:doc(), Rev :: barrel:revid()} | {put, Doc :: barrel:doc(), Attachments :: [attachment()]} | {put, Doc :: barrel:doc(), Attachments :: [attachment()], Rev :: barrel:revid()} | {post, Doc :: barrel:doc()} | {post, Doc :: barrel:doc(), IsUpsert :: boolean()} | {post, Doc :: barrel:doc(), Attachments :: [attachment()]} | {post, Doc :: barrel:doc(), Attachments :: [attachment()], IsUpsert :: boolean()} | {delete, DocId :: barrel:docid(), Rev :: barrel:revid()} | {put_rev, Doc :: barrel:doc(), History :: list(), Deleted :: boolean()} | {put_rev, Doc :: barrel:doc(), Attachments :: [attachment()], History :: list(), Deleted :: boolean()}. -export_type([ conn/0, docid/0, rev/0, db_infos/0, doc/0, read_option/0, read_options/0, write_options/0, fold_options/0, revid/0, revtree/0, change/0, batch_options/0, batch_results/0, batch_op/0, attid/0, att_description/0, attachment/0 ]). %% @doc create a database from its URL -spec create_database(DbUrl) -> Res when DbUrl :: binary(), Res :: ok | {error, any()}. create_database(Url0) -> {Url1, DbName} = name_from_url(Url0), DbObj = jsx:encode(#{ <<"database_id">> => DbName }), case hackney:request(<<"POST">>, Url1, [], DbObj, [with_body]) of {ok, 201, _, _} -> ok; Error -> Error end. %% @doc create a database with a configuration %% %% Example of config: %% #{ <<"database_id'>> => << "DbName">>, <<"index_mode">> => <<"consistent">> } %% %% Index Mode can be : <<"consistent">> | <<"lazy">>. -spec create_database(NodeUrl, Config) -> Res when NodeUrl :: binary(), DbUrl :: binary(), Config :: #{}, Res :: {ok, DbUrl} | {error, any()}. create_database(Url0, Config) -> Url1 = hackney_url: make_url(Url0, <<"dbs">>, []), DbObj = jsx:encode(Config), case hackney:request(<<"POST">>, Url1, [], DbObj, [with_body]) of {ok, 201, _, Obj} -> #{ <<"database_id">> := DbId} = jsx:decode(Obj, [return_maps]), DbUrl = hackney_url: make_url(Url0, [<<"dbs">>, DbId], []), {ok, DbUrl}; Error -> Error end. %% @doc delete a database from its URL -spec delete_database(DbUrl) -> Res when DbUrl :: binary(), Res :: ok | {error, any()}. delete_database(Url) -> case hackney:request(<<"DELETE">>, Url, [], <<>>, [with_body]) of {ok, 200, _, _} -> ok; Error -> Error end. %% @doc get all database names on the node -spec database_names(NodeUrl) -> Res when NodeUrl :: binary(), DbName :: binary(), Res :: [DbName] | {error, any()}. database_names(Url0) -> Url1 = hackney_url: make_url(Url0, <<"dbs">>, []), case hackney:request(<<"GET">>, Url1, [], <<>>, [with_body]) of {ok, 200, _, JsonBody} -> jsx:decode(JsonBody); Error -> Error end. %% @doc get database infos -spec database_infos(Url) -> Res when Url::binary(), Res::db_infos(). database_infos(Url) -> case hackney:request(<<"GET">>, Url, [], <<>>, [with_body]) of {ok, 200, _, JsonBody} -> jsx:decode(JsonBody, [return_maps]); Error -> Error end. %% @doc connect to a database from its URL. %% If the database is not found, an error is returned -spec connect(DbUrl) -> Res when DbUrl :: binary(), Res :: {ok, conn()} | {error, any()}. connect(Url) -> Max = application:get_env(barrel_httpc, max_connections, 12), {_, DbName} = name_from_url(Url), PoolName = binary_to_atom(DbName, latin1), _ = hackney_pool:start_pool(PoolName, [{pool_size, Max}]), case hackney:request(<<"HEAD">>, Url, [], <<>>, [{pool, PoolName}]) of {ok, 200, _} -> {ok, #{ pool => PoolName, db_url => Url}}; {ok, 404, _} -> _ = hackney_pool:stop_pool(PoolName), {error, not_found}; Error -> Error end. %% @doc retrieve a document by its key -spec get(Conn, DocId, Options) -> Res when Conn::conn(), DocId :: docid(), Options :: read_options(), Doc :: doc(), Meta :: meta(), Attachments :: [attachment()], Res :: {ok, Doc, Meta} | {ok, Doc, Attachments, Meta} | {error, not_found} | {error, any()}. get(Conn, DocId, Options0) when is_binary(DocId)-> {WithAttachment, Options1} = maybe_with_attachments(Options0), {Headers, Options2} = headers(Options1), Url = barrel_httpc_lib:make_url(Conn, [<<"docs">>, DocId], Options2), case request(Conn, <<"GET">>, Url, Headers, <<>>) of {ok, 200, RespHeaders, JsonBody} -> Doc = jsx:decode(JsonBody, [return_maps]), Meta = parse_header(RespHeaders), case WithAttachment of decoded -> {Attachments, DocWithoutAttachment} = maybe_take(<<"_attachments">>, Doc, []), DecodedAttachments = decode_attachments(Attachments), {ok, DocWithoutAttachment, DecodedAttachments, Meta}; raw -> {ok, Doc, Meta}; false -> {_, DocWithoutAttachment} = maybe_take(<<"_attachments">>, Doc, []), {ok, DocWithoutAttachment, Meta} end; Error -> Error end. %% @doc retrieve several documents -spec multi_get(Conn, Fun, AccIn, DocIds, Options) -> AccOut when Conn::conn(), Fun :: fun( (doc(), meta(), any()) -> any()), AccIn :: any(), DocIds :: [docid()], Options :: read_options(), AccOut :: any(). multi_get(_Db, _UserFun, AccIn, [], _Options) -> AccIn; multi_get(Db, UserFun, AccIn, DocIds, Options) -> WrapperFun = fun(Doc, Meta, Acc) -> {ok, UserFun(Doc, Meta, Acc)} end, {ok, Res} = barrel_httpc_fold:fold_by_id(Db, WrapperFun, AccIn, [{docids, DocIds} | Options]), Res. parse_header(HeadersList) -> Headers = hackney_headers_new:from_list(HeadersList), maybe_add_revisions( maybe_add_deleted( maybe_add_rev(#{}, Headers), Headers ), Headers ). maybe_add_rev(Meta, Headers) -> case hackney_headers_new:get_value(<<"etag">>, Headers) of undefined -> Meta; ETag -> Meta#{ <<"rev">> => ETag} end. maybe_add_deleted(Meta, Headers) -> case hackney_headers_new:get_value(<<"x-barrel-deleted">>, Headers) of <<"true">> -> Meta#{ <<"deleted">> => true }; _ -> Meta end. maybe_add_revisions(Meta, Headers) -> case hackney_headers_new:lookup(<<"x-barrel-revisions-id">>, Headers) of [] -> Meta; Values -> History = lists:flatten([binary:split(V, <<",">>, [global]) || {_, V} <- Values]), Meta#{ <<"revisions">> => barrel_doc:encode_revisions(History) } end. maybe_take(Key, Map, Default) when is_map(Map) -> case maps:take(Key, Map) of {K, M} -> {K,M}; error -> {Default, Map} end. maybe_with_attachments(Options) -> maybe_with_attachments(Options, false, []). maybe_with_attachments([], WithAttachment, Acc) -> {WithAttachment, lists:reverse(Acc)}; maybe_with_attachments([{attachments, all}|Options],_, Acc) -> maybe_with_attachments(Options, decoded, Acc); maybe_with_attachments([{attachments_parsing, false}|Options],_, Acc) -> maybe_with_attachments(Options, raw, Acc); maybe_with_attachments([H|Options], W, Acc) -> maybe_with_attachments(Options, W, [H|Acc]). %% @doc create or update a document. Return the new created revision %% with the docid or a conflict. -spec put(Conn, Doc, Options) -> Res when Conn::conn(), Doc :: doc(), Options :: write_options(), Res :: {ok, docid(), rev()} | {error, conflict} | {error, any()} | no_return(). put(Conn, #{ <<"id">> := DocId } = Doc, Options0) when is_binary(DocId) -> {Headers, Options1} = headers(Options0), Url = barrel_httpc_lib:make_url(Conn, [<<"docs">>, DocId], Options1), Async = proplists:get_value(async, Options1, false), post_put(Conn, <<"PUT">>, Doc, Url, Headers, Async); put(_, _, _) -> erlang:error({bad_doc, invalid_docid}). %% @doc update a document with attachments -spec put(Conn, Doc, Attachments, Options) -> Res when Conn::conn(), Doc :: doc(), Attachments :: [attachment()], Options :: write_options(), Res :: {ok, docid(), rev()} | ok | {error, conflict} | {error, any()} | no_return(). put(Conn, Doc, Attachments, Options0) when is_list(Attachments) -> case encode_attachments(Doc, Attachments) of {ok, DocWithAttachments} -> put(Conn, DocWithAttachments, Options0); {error, Error} -> {error, Error} end. post_put(Conn, Method, Doc, Url, Headers, Async) -> Body = jsx:encode(Doc), case request(Conn, Method, Url, Headers, Body) of {ok, Status, RespHeaders, JsonBody}=Resp -> case lists:member(Status, [200, 201, 202]) of true when Async =:= true -> ok; true -> Json = jsx:decode(JsonBody, [return_maps]), DocId = maps:get(<<"id">>, Json), RevId = proplists:get_value(<<"etag">>, RespHeaders), {ok, DocId, RevId}; false -> {error, {bad_response, Resp}} end; Error -> Error end. %% @doc delete a document -spec delete(Conn, DocId, Options) -> Res when Conn::conn(), DocId :: docid(), Options :: write_options(), Res :: {ok, docid(), rev()} | {error, conflict} | {error, any()}. delete(Conn, DocId, Options0) when is_binary(DocId) -> {Headers, Options1} = headers(Options0), Url = barrel_httpc_lib:make_url(Conn, [<<"docs">>, DocId], Options1), case request(Conn, <<"DELETE">>, Url, Headers, <<>>) of {ok, Status, _, JsonBody}=Resp -> case lists:member(Status, [200, 201]) of true -> Json = jsx:decode(JsonBody, [return_maps]), {ok, maps:get(<<"id">>, Json), maps:get(<<"rev">>, Json)}; false -> {error, {bad_response, Resp}} end; Error -> Error end. headers(Options) -> case proplists:get_value(rev, Options) of undefined -> {[{<<"Content-Type">>, <<"application/json">>}], proplists:delete(rev, Options)}; Rev -> Hdrs = [{<<"Content-Type">>, <<"application/json">>}, {<<"ETag">>, Rev}], {Hdrs, proplists:delete(rev, Options)} end. %% @doc create a document . Like put but only create a document without updating the old one. %% A doc shouldn't have revision. Optionally the document ID can be set in the doc. -spec post(Conn, Doc, Options) -> Res when Conn::conn(), Doc :: doc(), Options :: write_options(), Res :: {ok, docid(), rev()} | ok |{error, conflict} | {error, any()}. post(Conn, Doc, Options0) -> DocWithId = case maps:find(<<"id">>, Doc) of {ok, _Id} -> Doc; error -> Id = uuid:uuid_to_string(uuid:get_v4(), binary_standard), Doc#{<<"id">> => Id} end, {Headers, Options1} = headers(Options0), Url = barrel_httpc_lib:make_url(Conn, [<<"docs">>], Options1), Async = proplists:get_value(async, Options1, false), post_put(Conn, <<"POST">>, DocWithId, Url, Headers, Async). %% @doc create a document with attachments. -spec post(Conn, Doc, Attachments, Options) -> Res when Conn::conn(), Doc :: doc(), Attachments :: [attachment()], Options :: write_options(), Res :: {ok, docid(), rev()} | {error, conflict} | {error, any()}. post(Conn, Doc, Attachments, Options0) when is_list(Attachments) -> case encode_attachments(Doc, Attachments) of {ok, DocWithAttachments} -> post(Conn, DocWithAttachments, Options0); {error, Error} -> {error, Error} end. %% Atomically modifies the a document, this function takes the docId and pass the Doc and its attachments to the %% callback. -spec update_with(Conn, DocId, Fun, Options) -> Res when Conn::conn(), DocId :: docid(), Fun :: fun((Doc :: doc() | nil, Attachments :: list()) -> UpdatedDoc :: doc() | {UpdatedDoc :: doc(), UpdatedAttachments :: list()} ), Options :: read_options(), Res :: {ok, docid(), rev()} | {error, any()}. update_with(Conn, DocId, Fun, Options) -> case do_update_with(Conn, DocId, Fun, Options) of {ok, _, _} = OK -> OK; {error, {conflict, _}} -> update_with(Conn, DocId, Fun, Options); Error -> Error end. do_update_with(Conn, DocId, Fun, Options) -> case barrel_httpc:get(Conn, DocId, Options) of {ok, _, _} = Res -> try_put(Res, Conn, Fun); {ok, _, _, _} = Res -> try_put(Res, Conn, Fun); {error, not_found} -> try_post(Conn, Fun); Error -> Error end. try_put({ok, Doc, Meta}, Conn, Fun) -> Rev = maps:get(<<"rev">>, Meta), try_put_1(Fun(Doc, []), Rev, Conn); try_put({ok, Doc, Atts, Meta}, Conn, Fun) -> Rev = maps:get(<<"rev">>, Meta), try_put_1(Fun(Doc, Atts), Rev, Conn). try_put_1({Doc, Atts}, Rev, Conn) when is_map(Doc), is_list(Atts) -> barrel_httpc:put(Conn, Doc, Atts, [{rev, Rev}]); try_put_1(Doc, Rev, Conn) when is_map(Doc) -> barrel_httpc:put(Conn, Doc, [{rev, Rev}]). try_post(Conn, Fun) -> case Fun(nil, []) of Doc when is_map(Doc) -> barrel_httpc:post(Conn, Doc, []); {Doc, Atts} -> barrel_httpc:post(Conn, Doc, Atts, []) end. encode_attachments(Doc, Attachments) -> encode_attachments(Doc, Attachments, []). encode_attachments(Doc, [], []) -> {ok, Doc}; encode_attachments(Doc, [], EncodedAttachments) -> {ok, Doc#{<<"_attachments">> => lists:reverse(EncodedAttachments)}}; encode_attachments(Doc, [A|Tail], Encoded) -> case encode_attachment(A) of {ok, E} -> encode_attachments(Doc, Tail, [E|Encoded]); {error, Error} -> {error, Error} end. encode_attachment(#{<<"blob">> := Blob, <<"id">> := Id, <<"content-type">> := <<"application/erlang">>}) when is_binary(Blob) -> {error, {erlang_term_expected, Id}}; encode_attachment(#{<<"blob">> := Blob }=A) when is_binary(Blob) -> B64 = base64:encode(Blob), ContentType = maps:get(<<"content-type">>, A, <<"application/octet-stream">>), {ok, A#{<<"content-type">> => ContentType, <<"blob">> := B64, <<"content-length">> => byte_size(Blob)}}; encode_attachment(#{<<"blob">> := ErlangTerm}=A) -> TermAsBinary = term_to_binary(ErlangTerm), B64 = base64:encode(TermAsBinary), {ok, A#{<<"blob">> => B64, <<"content-type">> => <<"application/erlang">>, <<"content-length">> => byte_size(TermAsBinary)}}; encode_attachment(#{<<"link">> := Link}=A) -> B64 = base64:encode(Link), {ok, A#{<<"link">> := B64}}. decode_attachments(Attachments) -> [decode_attachment(A) || A <- Attachments]. decode_attachment(#{<<"content-type">> := <<"application/erlang">>}=A) -> #{<<"blob">> := B64} = A, Blob = base64:decode(B64), DecodedBlob = binary_to_term(Blob), A#{<<"blob">> => DecodedBlob}; decode_attachment(#{<<"blob">> := B64}=A) -> Blob = base64:decode(B64), A#{<<"blob">> := Blob}; decode_attachment(#{<<"link">> := B64}=A) -> Blob = base64:decode(B64), A#{<<"link">> := Blob}. %% @doc insert a specific revision to a a document. Useful for the replication. %% It takes the document id, the doc to edit and the revision history (list of ancestors). -spec put_rev(Conn, Doc, History, Deleted, Options) -> Res when Conn::conn(), Doc :: doc(), History :: [rev()], Deleted :: true | false, Options :: write_options(), Res :: {ok, docid(), rev()} | {error, conflict} | {error, any()}. put_rev(Conn, #{ <<"id">> := DocId } = Doc, History, Deleted, _Options) -> Req = #{ <<"document">> => Doc, <<"history">> => History, <<"deleted">> => Deleted }, Url = barrel_httpc_lib:make_url(Conn, [<<"docs">>, DocId], [{<<"edit">>, <<"true">>}]), Body = jsx:encode(Req), case request(Conn, <<"PUT">>, Url, [], Body) of {ok, Status, RespHeaders, JsonBody}=Resp -> case lists:member(Status, [200, 201]) of true -> Json = jsx:decode(JsonBody, [return_maps]), RevId = proplists:get_value(<<"etag">>, RespHeaders), DocId = maps:get(<<"id">>, Json), {ok, DocId, RevId}; false -> {error, {bad_response, Resp}} end; Error -> Error end; put_rev(_, _, _, _, _) -> erlang:error({bad_doc, invalid_docid}). %% @doc Apply the specified updates to the database. %% Note: The batch is not guaranteed to be atomic, atomicity is only guaranteed at the doc level. -spec write_batch(Conn, Updates, Options) -> Results when Conn :: conn(), Updates :: [batch_op()], Options :: batch_options(), Results :: batch_results(). write_batch(Conn, Updates, Options) -> Async = proplists:get_value(async, Options, false), Headers = [ {<<"Content-Type">>, <<"application/json">>}, {<<"x-barrel-write-batch">>, <<"true">>}, {<<"x-barrel-async">>, Async }], Url = barrel_httpc_lib:make_url(Conn, [<<"docs">>], []), JsonUpdate = [batch_update(Update) || Update <- Updates], Body = jsx:encode(#{ <<"updates">> => JsonUpdate }), case request(Conn, <<"POST">>, Url, Headers, Body) of {ok, Status, _RespHeaders, JsonBody}=Resp -> case lists:member(Status, [200]) of true -> Json = jsx:decode(JsonBody, [return_maps]), case maps:find(<<"results">>, Json) of {ok, Results} -> [ batch_result(Res) || Res <- Results ]; error -> ok end; false -> {error, {bad_response, Resp}} end; Error -> Error end. batch_update({post, Doc}) when is_map(Doc) -> #{ <<"op">> => <<"post">>, <<"doc">> => Doc }; batch_update({post, Doc0, Attachments}) when is_map(Doc0), is_list(Attachments) -> {ok, Doc1} = encode_attachments(Doc0, Attachments), #{ <<"op">> => <<"post">>, <<"doc">> => Doc1 }; batch_update({post, Doc, IsUpsert}) when is_map(Doc), is_boolean(IsUpsert) -> #{ <<"op">> => <<"post">>, <<"doc">> => Doc, <<"is_upsert">> => IsUpsert }; batch_update({post, Doc0, Attachments, IsUpsert}) when is_map(Doc0), is_list(Attachments), is_boolean(IsUpsert) -> {ok, Doc1} = encode_attachments(Doc0, Attachments), #{ <<"op">> => <<"post">>, <<"doc">> => Doc1, <<"is_upsert">> => IsUpsert }; batch_update({put, Doc}) when is_map(Doc) -> #{ <<"op">> => <<"put">>, <<"doc">> => Doc }; batch_update({put, Doc0, Attachments}) when is_map(Doc0), is_list(Attachments) -> {ok, Doc1} = encode_attachments(Doc0, Attachments), #{ <<"op">> => <<"put">>, <<"doc">> => Doc1 }; batch_update({put, Doc, Rev}) when is_map(Doc), is_binary(Rev) -> #{ <<"op">> => <<"put">>, <<"doc">> => Doc, <<"rev">> => Rev }; batch_update({put, Doc0, Attachments, Rev}) when is_map(Doc0), is_list(Attachments), is_binary(Rev) -> {ok, Doc1} = encode_attachments(Doc0, Attachments), #{ <<"op">> => <<"put">>, <<"doc">> => Doc1, <<"rev">> => Rev }; batch_update({delete, DocId}) when is_binary(DocId) -> #{ <<"op">> => <<"delete">>, <<"id">> => DocId }; batch_update({delete, DocId, Rev}) when is_binary(DocId), is_binary(Rev) -> #{ <<"op">> => <<"delete">>, <<"id">> => DocId, <<"rev">> => Rev }; batch_update({put_rev, Doc, History, Deleted}) when is_binary(Doc), is_binary(History), is_boolean(Deleted) -> #{ <<"op">> => <<"put_rev">>, <<"doc">> => Doc, <<"history">> => History, <<"deleted">> => Deleted }; batch_update( {put_rev, Doc0, Attachments, History, Deleted} ) when is_binary(Doc0), is_list(Attachments), is_binary(History), is_boolean(Deleted) -> {ok, Doc1} = encode_attachments(Doc0, Attachments), #{ <<"op">> => <<"put_rev">>, <<"doc">> => Doc1, <<"history">> => History, <<"deleted">> => Deleted }; batch_update(_) -> erlang:error(badarg). batch_result(#{ <<"status">> := <<"ok">>, <<"id">> := DocId, <<"rev">> := Rev }) -> {ok, DocId, Rev}; batch_result(#{ <<"status">> := <<"error">>, <<"reason">> := <<"not found">> }) -> {error, not_found}; batch_result(#{ <<"status">> := <<"error">>, <<"reason">> := Other }) -> {error, Other}; batch_result(#{ <<"status">> := <<"conflict">>, <<"reason">> := <<"doc exists">> }) -> {error, {conflict, doc_exists}}; batch_result(#{ <<"status">> := <<"conflict">>, <<"reason">> := <<"revision conflict">> }) -> {error, {conflict, revision_conflict}}. %% @doc get all revisions ids that differ in a doc from the list given -spec revsdiff(Conn, DocId, RevIds) -> Res when Conn::conn(), DocId :: docid(), RevIds :: [revid()], Res:: {ok, Missing :: [revid()], PossibleAncestors :: [revid()]} | {error, any()}. revsdiff(Conn, DocId, RevIds) -> case revsdiff(Conn, #{ DocId => RevIds }) of {ok, Res} -> #{ DocId := #{ <<"missing">> := Missing, <<"possible_ancestors">> := PossibleAncestors}} = Res, {ok, Missing, PossibleAncestors}; Error -> Error end. %% @doc get all revisions ids that differ in docs from the list given. %% Docs are passed in the object where eack Key is the document ID and %% the value the list of the revisions to compare. -spec revsdiff(Conn, Docs) -> Res when Conn :: conn(), Docs :: #{ docid() => [revid()]}, Res :: {ok, #{ docid() => map() }} | {error, any()}. revsdiff(Conn, Docs) when is_map(Docs) -> Url = barrel_httpc_lib:make_url(Conn, [<<"revsdiff">>], []), Body = jsx:encode(Docs), Headers = [{<<"Content-Type">>, <<"application/json">>}], case request(Conn, <<"POST">>, Url, Headers, Body) of {ok, 200, _, JsonBody} -> Result = jsx:decode(JsonBody, [return_maps]), {ok, Result}; Error -> Error end; revsdiff(_, _) -> erlang:error(badarg). %% @doc fold all docs by Id -spec fold_by_id(Conn, Fun, AccIn, Options) -> AccOut | Error when Conn::conn(), FunRes :: {ok, Acc2::any()} | stop | {stop, Acc2::any()}, Fun :: fun((Doc :: doc(), Acc1 :: any()) -> FunRes), Options :: fold_options(), AccIn :: any(), AccOut :: any(), Error :: {error, term()}. fold_by_id(Db, Fun, Acc, Options) -> barrel_httpc_fold:fold_by_id(Db, Fun, Acc, Options). %% @doc fold all docs using a Pointer to the doc -spec fold_by_path(Conn, Path, Fun, AccIn, Options) -> AccOut | Error when Conn::conn(), Path::binary(), FunRes :: {ok, Acc2::any()} | stop | {stop, Acc2::any()}, Fun :: fun((Doc :: doc(), Acc1 :: any()) -> FunRes), Options :: fold_options(), AccIn :: any(), AccOut :: any(), Error :: {error, term()}. fold_by_path(Conn, Path, Fun, AccIn, Options) -> barrel_httpc_fold:fold_by_path(Conn, Path, Fun, AccIn, Options). %% @doc fold all changes since last sequence -spec changes_since(Conn, Since, Fun, AccIn, Opts) -> AccOut when Conn::conn(), Since :: non_neg_integer(), FunRes :: {ok, Acc2::any()} | stop | {stop, Acc2::any()}, Fun :: fun((Change :: change(), Acc :: any()) -> FunRes), AccIn :: any(), AccOut :: any(), Opts :: list(). changes_since(Conn, Since, Fun, AccIn, Opts) -> barrel_httpc_fold:changes_since(Conn, Since, Fun, AccIn, Opts). -spec attach(Conn, DocId, AttDescription, Options) -> Res when Conn :: conn(), DocId :: docid(), AttDescription :: att_description(), Options :: list(), RevId :: revid(), Res :: {ok, DocId, RevId} | {error, any()}. attach(Db, DocId, AttDescription, Options) -> barrel_httpc_attachments:attach(Db, DocId, AttDescription, Options). -spec attach(Conn, DocId, AttDescription, Binary, Options) -> Res when Conn :: conn(), DocId :: docid(), AttDescription :: att_description(), Binary :: binary(), Options :: list(), RevId :: revid(), Res :: {ok, DocId, RevId}. attach(Db, DocId, AttDescription, Binary, Options) -> barrel_httpc_attachments:attach(Db, DocId, AttDescription, Binary, Options). -spec get_attachment(Conn, DocId, AttId, Options) -> Res when Conn :: conn(), DocId :: docid(), AttId :: att_description(), Options :: list(), AttDescription :: att_description(), Res :: {ok, AttDescription}. get_attachment(Db, DocId, AttId, Options) -> barrel_httpc_attachments:get_attachment(Db, DocId, AttId, Options). -spec get_attachment_binary(Conn, DocId, AttId, Options) -> Res when Conn :: conn(), DocId :: docid(), AttId :: attid(), Options :: list(), Binary :: binary(), Res :: {ok, Binary}. get_attachment_binary(Db, DocId, AttId, Options) -> barrel_httpc_attachments:get_attachment_binary(Db, DocId, AttId, Options). -spec replace_attachment(Conn, DocId, AttId, AttDescription, Options) -> Res when Conn :: conn(), DocId :: docid(), AttId :: attid(), AttDescription :: att_description(), Options :: list(), RevId :: revid(), Res :: {ok, DocId, RevId}. replace_attachment(Db, DocId, AttId, AttDescription, Options) -> barrel_httpc_attachments:replace_attachment(Db, DocId, AttId, AttDescription, Options). -spec replace_attachment_binary(Conn, DocId, AttId, Binary, Options) -> Res when Conn :: conn(), DocId :: docid(), AttId :: attid(), Binary :: binary(), Options :: list(), RevId :: revid(), Res :: {ok, DocId, RevId}. replace_attachment_binary(Db, DocId, AttId, Binary, Options) -> barrel_httpc_attachments:replace_attachment_binary(Db, DocId, AttId, Binary, Options). -spec delete_attachment(Conn, DocId, AttId, Options) -> Res when Conn :: conn(), DocId :: docid(), AttId :: attid(), Options :: list(), RevId :: revid(), Res :: {ok, DocId, RevId}. delete_attachment(Db, DocId, AttId, Options) -> barrel_httpc_attachments:delete_attachment(Db, DocId, AttId, Options). -spec attachments(Conn, DocId, Options) -> Res when Conn :: conn(), DocId :: docid(), Options :: list(), Res :: [att_description()]. attachments(Db, DocId, Options) -> barrel_httpc_attachments:attachments(Db, DocId, Options). get_system_doc(Conn, DocId) -> Url = barrel_httpc_lib:make_url(Conn, [<<"system">>, DocId], []), case request(Conn, <<"GET">>, Url) of {ok, 200, _, JsonBody} -> {ok, jsx:decode(JsonBody, [return_maps])}; Error -> Error end. put_system_doc(Conn, DocId, Doc) when is_map(Doc) -> Url = barrel_httpc_lib:make_url(Conn, [<<"system">>, DocId], []), Body = jsx:encode(Doc), case request(Conn, <<"PUT">>, Url, [], Body) of {ok, Status, _, _JsonBody}=Resp -> case lists:member(Status, [200, 201]) of true -> ok; false -> {error, {bad_response, Resp}} end; Error -> Error end; put_system_doc(_, _, _) -> erlang:error(bad_doc). delete_system_doc(Conn, DocId) -> Url = barrel_httpc_lib:make_url(Conn, [<<"system">>, DocId], []), case request(Conn, <<"DELETE">>, Url) of {ok, 200, _, _JsonBody} -> ok; Error -> Error end. %% @doc start a change listener on the database. %% This function create a process that will listen on the changes feed API. %% If not callback is given, changes are queued in the process and need %% to be fetched using the `fetch_changes' function. When a callback is given, %% a change is passed to the function, no state is kept in the process. %% a change given to the callback or in the list is under the following form %% #{ %% <<"id">> := binary(), % id of the document updated %% <<"seq">> := non_neg_integer(), % sequence of the change %% <<"changes">> => [revid(], % revision id of the change or %% % the full history if history is true (from last to first), %% <<"deleted">> => true | false % present if deleted %%} %% %% In case the connection is lost or closed, it will retry to connect, at most %% `max_retry` times (default=5 times), waiting `delay_before_retry` ms between each %% try (default=500 ms) -spec start_changes_listener(Conn, ListenerOptions) -> Res when Conn :: barrel_httpc:conn(), ListenerOptions :: barrel_httpc_changes:listener_options(), ListenerPid :: pid(), Res :: {ok, ListenerPid} | {error, any()}. start_changes_listener(Conn, ListenerOptions) -> barrel_httpc_changes:start_link(Conn, ListenerOptions). %% @doc stop a change listener -spec stop_changes_listener(ListenerPid) -> Res when ListenerPid :: pid(), Res :: ok. stop_changes_listener(ListenerPid) -> barrel_httpc_changes:stop(ListenerPid). %% @doc fetch all changes received by a listener à that time. %% Only useful when no changes callback is given. %% Otherwise the list will always be empty. -spec get_changes(ListenerPid) -> Changes when ListenerPid :: pid(), Changes :: [barrel_httpc:change()]. get_changes(ListenerPid) -> barrel_httpc_changes:changes(ListenerPid). %% internal name_from_url(Url) -> #hackney_url{path=Path} = Parsed = hackney_url:parse_url(Url), Parts = binary:split(Path, <<"/">>, [global]), Path2 = barrel_httpc_lib:binary_join( lists:sublist(Parts, length(Parts) -1), <<"/">> ), Url2 = hackney_url:unparse_url(Parsed#hackney_url{path=Path2}), {Url2, lists:last(Parts)}. make_headers(Headers) -> case proplists:get_value(<<"Accept">>, Headers) of undefined -> [{<<"Accept">>, <<"application/json, */*;q=0.9">>} | Headers]; _ -> Headers end. request(Conn, Method, Url) -> request(Conn, Method, Url, [], <<>>). request(#{pool := Pool}, Method, Url, Headers0, Body) -> Headers1 = make_headers(Headers0), Options = [with_body, {pool, Pool}], Resp = hackney:request(Method, Url, Headers1, Body, Options), db_resp(Resp). db_resp({ok, 401, _}) -> {error, not_authenticated}; db_resp({ok, 403, _}) -> {error, forbidden}; db_resp({ok, 404, _}) -> {error, not_found}; db_resp({ok, 409, _}) -> {error, conflict}; db_resp({ok, 412, _}) -> {error, precondition_failed}; db_resp({ok, Status, _}) when Status >= 500 -> {error, server_error}; db_resp({ok, _, _}=Resp) -> Resp; db_resp({ok, 401, _, _}) -> {error, not_authenticated}; db_resp({ok, 403, _, _}) -> {error, forbidden}; db_resp({ok, 404, _, _}) -> {error, not_found}; db_resp({ok, 409, _, _}) -> {error, conflict}; db_resp({ok, 412, _, _}) -> {error, precondition_failed}; db_resp({ok, Status, _, Body}) when Status >= 500 -> {error, {server_error, Body}}; db_resp(Resp) -> Resp. ================================================ FILE: apps/barrel_httpc/src/barrel_httpc_app.erl ================================================ %%%------------------------------------------------------------------- %% @doc barrel_httpc public API %% @end %%%------------------------------------------------------------------- -module(barrel_httpc_app). -behaviour(application). %% Application callbacks -export([start/2, stop/1]). %%==================================================================== %% API %%==================================================================== start(_StartType, _StartArgs) -> barrel_httpc_sup:start_link(). %%-------------------------------------------------------------------- stop(_State) -> ok. %%==================================================================== %% Internal functions %%==================================================================== ================================================ FILE: apps/barrel_httpc/src/barrel_httpc_attachments.erl ================================================ %% Copyright 2016, Bernard Notarianni %% %% Licensed under the Apache License, Version 2.0 (the "License"); you may not %% use this file except in compliance with the License. You may obtain a copy of %% the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT %% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the %% License for the specific language governing permissions and limitations under %% the License. -module(barrel_httpc_attachments). -author("Bernard Notarianni"). -export([attach/4]). -export([attach/5]). -export([get_attachment/4]). -export([get_attachment_binary/4]). -export([replace_attachment/5]). -export([replace_attachment_binary/5]). -export([delete_attachment/4]). -export([attachments/3]). -define(ATTTAG, <<"_attachments">>). -spec attach(Conn, DocId, AttDescription, Options) -> Res when Conn :: barrel_httpc:conn(), DocId :: barrel_httpc:docid(), AttDescription :: barrel_httpc:att_description(), Options :: barrel_httpc:read_options(), Res :: {ok, barrel_httpc:docid(), barrel_httpc:rev()} | ok | {error, term()}. attach(Conn, DocId, AttDescription, Options) -> case barrel_httpc:get(Conn, DocId, [{attachments, all}|Options]) of {ok, Doc, Attachments, Meta} -> AttId = maps:get(<<"id">>, AttDescription), AttOpts = [{rev, maps:get(<<"rev">>, Meta)}], case find_att_doc(Attachments, AttId) of {ok, _} -> {error, attachment_conflict}; {error, not_found} -> Attachments2 = [AttDescription|Attachments], barrel_httpc:put(Conn, Doc, Attachments2, AttOpts) end; {error, _} = Error -> Error end. -spec attach(Conn, DocId, AttDescription, AttBin, Options) -> Res when Conn :: barrel_httpc:conn(), DocId :: barrel_httpc:docid(), AttDescription :: barrel_httpc:att_description(), AttBin :: binary(), Options :: barrel_httpc:read_options(), Res :: {ok, barrel_httpc:docid(), barrel_httpc:rev()} | ok | {error, term()}. attach(Conn, DocId, AttDescription, AttBin, Options) when is_binary(AttBin) -> attach(Conn, DocId, AttDescription#{<<"blob">> => AttBin}, Options). -spec get_attachment(Conn, DocId, AttId, Options) -> Res when Conn :: barrel_httpc:conn(), DocId :: barrel_httpc:docid(), AttId :: binary(), Options :: barrel_httpc:write_options(), AttDescription :: barrel_httpc:att_description(), Res :: {ok, AttDescription} | {error, term()}. get_attachment(Conn, DocId, AttId, Options) -> case barrel_httpc:get(Conn, DocId, [{attachments, all}|Options]) of {ok, _, Attachments, _} -> find_att_doc(Attachments, AttId); {error, _} = Error -> Error end. -spec get_attachment_binary(Conn, DocId, AttId, Options) -> Res when Conn :: barrel_httpc:conn(), DocId :: barrel_httpc:docid(), AttId :: binary(), AttBin :: binary(), Options :: barrel_httpc:read_options(), Res :: {ok, AttBin} | {error, not_found}. get_attachment_binary(Conn, DocId, AttId, Options) -> case barrel_httpc:get(Conn, DocId, [{attachments, all}|Options]) of {ok, _, Attachments, _} -> case find_att_doc(Attachments, AttId) of {ok, Attachment} -> Data = maps:get(<<"blob">>, Attachment), {ok, Data}; {error, not_found} -> {error, not_found} end; {error, _} = Error -> Error end. -spec replace_attachment(Conn, DocId, AttId, AttDescription, Options) -> Res when Conn :: barrel_httpc:conn(), DocId :: barrel_httpc:docid(), AttId :: binary(), AttDescription :: barrel_httpc:att_description(), Options :: barrel_httpc:write_options(), Res :: {ok, barrel_httpc:docid(), barrel_httpc:rev()} | ok | {error, term()}. replace_attachment(Conn, DocId, AttId, AttDescription, Options) -> {ok, Doc, Attachments, Meta} = barrel_httpc:get(Conn, DocId, [{attachments, all}|Options]), AttId = maps:get(<<"id">>, AttDescription), AttOpts = [{rev, maps:get(<<"rev">>, Meta)}], %% make new attachment and update the doc NewAttachments = replace_att_doc(AttId, AttDescription, Attachments), barrel_httpc:put(Conn, Doc, NewAttachments, AttOpts). -spec replace_attachment_binary(Conn, DocId, AttId, AttBin, Options) -> Res when Conn :: barrel_httpc:conn(), DocId :: barrel_httpc:docid(), AttId :: binary(), AttBin :: binary(), Options :: barrel_httpc:write_options(), Res :: {ok, barrel_httpc:docid(), barrel_httpc:rev()} | ok | {error, term()}. replace_attachment_binary(Conn, DocId, AttId, AttBin, Options) when is_binary(AttBin) -> {ok, _Doc, Attachments, _Meta} = barrel_httpc:get(Conn, DocId, [{attachments, all}|Options]), case find_att_doc(Attachments, AttId) of {error, not_found} -> {error, not_found}; {ok, Attachment} -> NewAttachment = Attachment#{<<"blob">> => AttBin}, replace_attachment(Conn, DocId, AttId, NewAttachment, Options) end. -spec delete_attachment(Conn, DocId, AttId, Options) -> Res when Conn :: barrel_httpc:conn(), DocId :: barrel_httpc:docid(), AttId :: binary(), Options :: barrel_httpc:write_options(), Res :: {ok, barrel_httpc:docid(), barrel_httpc:rev()} | {error, term()}. delete_attachment(Conn, DocId, AttId, Options) -> {ok, Doc, Attachments, Meta} = barrel_httpc:get(Conn, DocId, [{attachments, all}|Options]), NewAttachments = delete_att_doc(AttId, Attachments), PutOpts = [{rev, maps:get(<<"rev">>, Meta)}], barrel_httpc:put(Conn, Doc, NewAttachments, PutOpts). -spec attachments(Conn, DocId, Options) -> Attachments when Conn :: barrel_httpc:conn(), DocId :: barrel_httpc:docid(), Options :: barrel_httpc:read_options(), Attachments :: [barrel_httpc:attachment()]. attachments(Conn, DocId, Options) -> {ok, _, Attachments, _} = barrel_httpc:get(Conn, DocId, [{attachments, all}|Options]), Attachments. %% ============================================================================= %% Internals %% ============================================================================= find_att_doc([#{<<"id">> := AttId}=AttDoc|_], AttId) -> {ok, AttDoc}; find_att_doc([_|Rest], AttId) -> find_att_doc(Rest, AttId); find_att_doc([], _AttId) -> {error, not_found}. replace_att_doc(_,_, []) -> []; replace_att_doc(AttId, NewAttDoc, [#{<<"id">> := AttId}|Tail]) -> [NewAttDoc|replace_att_doc(AttId, NewAttDoc, Tail)]; replace_att_doc(AttId, NewAttDoc, [Head|Tail]) -> [Head|replace_att_doc(AttId, NewAttDoc, Tail)]. delete_att_doc(_, []) -> []; delete_att_doc(AttId, [#{<<"id">> := AttId}|Tail]) -> delete_att_doc(AttId, Tail); delete_att_doc(AttId, [Head|Tail]) -> [Head|delete_att_doc(AttId, Tail)]. ================================================ FILE: apps/barrel_httpc/src/barrel_httpc_changes.erl ================================================ %% Copyright 2017, Benoit Chesneau %% %% Licensed under the Apache License, Version 2.0 (the "License"); you may not %% use this file except in compliance with the License. You may obtain a copy of %% the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT %% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the %% License for the specific language governing permissions and limitations under %% the License. -module(barrel_httpc_changes). -export([ start_link/2, parse_change/1, changes/1, stop/1 ]). -export([ init/3, init_feed/1, wait_changes/1 ]). -export([ system_continue/3, system_code_change/4, system_terminate/4 ]). -type listener_options() :: #{ since => non_neg_integer(), mode => binary | sse, include_doc => true | false, history => true | false, changes_cb => fun( (barrel_peer:change()) -> ok ), timeout => non_neg_integer(), max_retry => non_neg_integer(), delay_before_retry => non_neg_integer() }. -export_type([listener_options/0]). -define(DEFAULT_TIMEOUT, 60000). -define(DEFAULT_HEARTBEAT, 30000). -define(DEFAULT_MAX_RETRY, 3). -define(RETRY_TIMEOUT, 5000). -record(state, { parent :: pid(), conn, ref, hackney_timeout :: non_neg_integer(), last_seq :: undefined | non_neg_integer(), since :: undefined | non_neg_integer(), changes, mode :: term(), changes_cb, buffer, retry :: {non_neg_integer(), non_neg_integer(), non_neg_integer()}, options :: map() }). %% fetch all changes received by a listener à that time. %% Only useful when no changes callback is given. %% Otherwise the list will always be empty. -spec changes(ListenerPid) -> Changes when ListenerPid :: pid(), Changes :: [barrel_httpc:change()]. changes(FeedPid) -> Tag = make_ref(), MRef = erlang:monitor(process, FeedPid), FeedPid ! {get_changes, self(), Tag}, receive {changes, Tag, Changes} -> Changes; {'DOWN', MRef, _, _, Reason} -> exit(Reason) after ?DEFAULT_TIMEOUT -> erlang:demonitor(MRef, [flush]), exit(timeout) end. %% @doc start a change listener on the database. %% This function create a process that will listen on the changes feed API. %% If not callback is given, changes are queued in the process and need %% to be fetched using the `fetch_changes' function. When a callback is given, %% a change is passed to the function, no state is kept in the process. %% a change given to the callback or in the list is under the following form %% #{ %% <<"id">> := binary(), % id of the document updated %% <<"seq">> := non_neg_integer(), % sequence of the change %% <<"changes">> => [revid(], % revision id of the change or %% % the full history if history is true (from last to first), %% <<"deleted">> => true | false % present if deleted %%} %% %% In case the connection is lost or closed, it will retry to connect, at most %% `max_retry` times (default=5 times), waiting `delay_before_retry` ms between each %% try (default=500 ms) -spec start_link(Conn, ListenerOptions) -> Res when Conn :: barrel_httpc:conn(), ListenerOptions :: listener_options(), ListenerPid :: pid(), Res :: {ok, ListenerPid} | {error, any()}. start_link(Conn, Options) when is_map(Options) -> proc_lib:start_link(?MODULE, init, [self(), Conn, Options]). %% @doc stop a change listener -spec stop(ListenerPid) -> Res when ListenerPid :: pid(), Res :: ok. stop(FeedPid) -> MRef = erlang:monitor(process, FeedPid), FeedPid ! stop, receive {'DOWN', MRef, _, _, _} -> ok end. %% @doc parse a binary change fetched when start_listener mod is binary -spec parse_change(binary()) -> barrel_httpc:change(). parse_change(ChangeBin) -> Lines = binary:split(ChangeBin, <<"\n">>, [global]), lists:foldl( fun(Line, Acc) -> case Line of << "data: ", Change/binary >> -> jsx:decode(Change, [return_maps]); _ -> Acc end end, #{}, Lines ). init(Parent, Conn, Options) -> process_flag(trap_exit, true), proc_lib:init_ack(Parent, {ok, self()}), %% initialize the state State = #state{ parent = Parent, conn = Conn, retry = reset_retry(Options), hackney_timeout = maps:get(timeout, Options, ?DEFAULT_TIMEOUT), options = Options}, init_feed(State). reset_retry(Options) -> Retries = maps:get(retry, Options, ?DEFAULT_MAX_RETRY), RetryTimeout = maps:get(retry_timeout, Options, ?RETRY_TIMEOUT), {Retries, 200, RetryTimeout}. init_feed(State) -> #state{ conn = Conn, last_seq = LastSeq, options = Options } = State, Since = case LastSeq of undefined -> maps:get(since, Options, 0); Seq -> Seq end, Headers = case Since of 0 -> [{<<"Accept">>, <<"text/event-stream">>}]; Since -> [{<<"Accept">>, <<"text/event-stream">>}, {<<"Last-Event-Id">>, integer_to_binary(Since)}] end, Params0 = parse_options(Options), Params = case proplists:is_defined(<<"heartbeat">>, Params0) of true -> Params0; _ -> [{<<"heartbeat">>, ?DEFAULT_HEARTBEAT}|Params0] end, Url = barrel_httpc_lib:make_url(Conn, <<"docs">>, Params), ReqOpts = [{pool, none}, {async, once}, {recv_timeout, infinity}], case hackney:request(<<"GET">>, Url, Headers, <<>>, ReqOpts) of {ok, Ref} -> wait_response(State#state{ ref = Ref, retry = reset_retry(Options) }); Error -> _ = lager:error("~s: ~p~n", [?MODULE_STRING, Error]), maybe_retry(State, Error) end. maybe_retry(State, ExitReason) -> #state{ ref = Ref, retry = {Retries, Delay, Max} } = State, _ = (catch hackney:close(Ref)), if Retries /= 0 -> _ = lager:warning("~s retrying connection...~n", [?MODULE_STRING]), _ = erlang:send_after(Delay, self(), connect), State2 = State#state{ retry={Retries - 1, rand_increment(Delay, Max), Max} }, wait_retry(State2); true -> _ = lager:warning("~s: num of retries exceeded the limit.~n", [?MODULE_STRING]), cleanup(State, ExitReason), exit(normal) end. wait_retry(State = #state{parent = Parent}) -> receive connect -> init_feed(State); {'EXIT', Parent, _} -> cleanup(State, "parent stopped"), exit(normal); {system, From, Request} -> sys:handle_system_msg( Request, From, Parent, ?MODULE, [], {wait_retry, State}) end. wait_response(#state{ parent = Parent, ref = Ref, options = Options}=State) -> receive {hackney_response, Ref, {status, 200, _}} -> Conn = State#state.conn, _ = lager:info("[~s] connected to conn=~p", [?MODULE_STRING, Conn]), Cb = maps:get(changes_cb, Options, nil), Mode = maps:get(mode, Options, binary), State2 = State#state{changes = queue:new(), mode = Mode, changes_cb = Cb, buffer = <<>>}, wait_changes(State2); {hackney_response, Ref, {status, 404, _}} -> _ = lager:error("~s not_found ~n", [?MODULE_STRING]), cleanup(Ref, not_found), exit(not_found); {hackney_response, Ref, {status, Status, Reason}} -> _ = lager:error( "~s request bad status ~p(~p)~n", [?MODULE_STRING, Status, Reason] ), maybe_retry(State, {http_error, Status, Reason}); {hackney_response, Ref, {error, closed}} -> _ = lager:warning("[~s] hackney connection closed", [?MODULE_STRING]), maybe_retry(State, normal); {hackney_response, Ref, {error, Reason}} -> _ = lager:error( "~s hackney error: ~p~n", [?MODULE_STRING, Reason] ), cleanup(Ref, Reason), exit(Reason); {'EXIT', Parent, _} -> cleanup(State, "parent stopped"), exit(normal); {system, From, Request} -> sys:handle_system_msg( Request, From, Parent, ?MODULE, [], {wait_response, State}) after State#state.hackney_timeout -> cleanup(State, timeout), exit(timeout) end. wait_changes(#state{ parent = Parent, ref = Ref }=State) -> _ = hackney:stream_next(Ref), receive {get_changes, Pid, Tag} -> {Events, NewState} = get_changes(State), Pid ! {changes, Tag, Events}, wait_changes(NewState); {hackney_response, Ref, {headers, _Headers}} -> wait_changes(State); {hackney_response, Ref, done} -> _ = lager:warning("[~s] hackney connection done", [?MODULE_STRING]), maybe_retry(State, normal); {hackney_response, Ref, Data} when is_binary(Data) -> decode_data(Data, State); {hackney_response, Ref, Error} -> _ = lager:error( "~s hackney error: ~p~n", [?MODULE_STRING, Error] ), cleanup(State, Error), exit(Error); stop -> cleanup(State, "listener stopped"), exit(normal); {'EXIT', Parent, _} -> cleanup(State, "parent stopped"), exit(normal); {system, From, Request} -> sys:handle_system_msg( Request, From, Parent, ?MODULE, [], {wait_changes, State}) after State#state.hackney_timeout -> _ = lager:error("~s timeout: ~n", [?MODULE_STRING]), cleanup(State, timeout), exit(timeout) end. system_continue(_, _, {wait_retry, State}) -> wait_retry(State); system_continue(_, _, {wait_response, State}) -> wait_response(State); system_continue(_, _, {wait_changes, State}) -> wait_changes(State). -spec system_terminate(any(), _, _, _) -> no_return(). system_terminate(Reason, _, _, #{ ref := Ref }) -> %% unregister the stream catch hackney:close(Ref), _ = lager:debug( "~s terminate: ~p", [?MODULE_STRING,Reason] ), exit(Reason). system_code_change(Misc, _, _, _) -> {ok, Misc}. cleanup(#state{ ref = Ref }, Reason) -> cleanup(Ref, Reason); cleanup(Ref, Reason) -> _ = lager:info("closing change feed connection: ~p", [Reason]), (catch hackney:close(Ref)), ok. get_changes(#state{ changes = Q }=State) -> Changes = queue:to_list(Q), {Changes, State#state{ changes = queue:new() }}. decode_data(Data, #state{ mode = binary, last_seq = OldSeq, changes = Q, changes_cb = nil }=State) -> {Changes, NewState} = sse_changes(Data, State), DecodeFun = fun(C) -> C end, {LastSeq, Q2} = queue_change(Changes, DecodeFun, OldSeq, Q), wait_changes(NewState#state{ last_seq = LastSeq, changes = Q2 }); decode_data(Data, #state{ changes = Q, last_seq = OldSeq, changes_cb = nil }=State) -> {Changes, NewState} = sse_changes(Data, State), {LastSeq, Q2} = queue_change(Changes, fun parse_change/1, OldSeq, Q), wait_changes(NewState#state{ last_seq = LastSeq, changes = Q2 }); decode_data(Data, #state{ mode = Mode, last_seq = OldSeq, changes_cb = Cb }=State) -> {Changes, NewState} = sse_changes(Data, State), LastSeq = handle_changes(Changes, Mode, Cb, OldSeq), wait_changes(NewState#state{last_seq = LastSeq}). queue_change([<<>> | Rest], Fun, Last, Queue) -> queue_change(Rest, Fun, Last, Queue); queue_change([Change | Rest], Fun, _Last, Queue) -> #{<<"seq">> := Seq} = parse_change(Change), queue_change(Rest, Fun, Seq, queue:in(Fun(Change), Queue)); queue_change([], _Fun, Last, Queue) -> {Last, Queue}. handle_changes([<<>> | Rest], Mode, Cb, Last) -> handle_changes(Rest, Mode, Cb, Last); handle_changes([ChangeBin | Rest], Mode, Cb, _Last) -> #{<<"seq">> := Seq} = Change = parse_change(ChangeBin), case Mode of binary -> Cb(ChangeBin); _ -> Cb(Change) end, handle_changes(Rest, Mode, Cb, Seq); handle_changes([], _Mode, _Cb, Last) -> Last. sse_changes(Data, #state{ buffer = Buffer }=State) -> NewBuffer = << Buffer/binary, Data/binary >>, DataList = binary:split(NewBuffer, <<"\n\n">>, [global]), case lists:reverse(DataList) of [<<>> | Changes] -> {lists:reverse(Changes), State#state{ buffer = <<>> }}; [Rest | Changes] -> {lists:reverse(Changes), State#state{ buffer = Rest }} end. parse_options(Options) -> maps:fold( fun (include_doc, IncludeDocs, Acc) -> [{<<"include_doc">>, IncludeDocs} | Acc]; (history, History, Acc) -> [{<< "history" >>, History} | Acc]; (heartbeat, Heartbeat, Acc) -> [{<< "heartbeat" >>, Heartbeat} | Acc]; (_, _, Acc) -> Acc end, [], Options ). rand_increment(N) -> %% New delay chosen from [N, 3N], i.e. [0.5 * 2N, 1.5 * 2N] Width = N bsl 1, N + rand:uniform(Width + 1) - 1. rand_increment(N, Max) -> %% The largest interval for [0.5 * Time, 1.5 * Time] with maximum Max is %% [Max div 3, Max]. MaxMinDelay = Max div 3, if MaxMinDelay =:= 0 -> rand:uniform(Max); N > MaxMinDelay -> rand_increment(MaxMinDelay); true -> rand_increment(N) end. ================================================ FILE: apps/barrel_httpc/src/barrel_httpc_fold.erl ================================================ %%%------------------------------------------------------------------- %%% @author benoitc %%% @copyright (C) 2017, %%% @doc %%% %%% @end %%% Created : 18. Jan 2017 14:59 %%%------------------------------------------------------------------- -module(barrel_httpc_fold). -author("benoitc"). %% API -export([ fold_by_id/4, fold_by_path/5, changes_since/5 ]). -export([ init/1, handle_event/2, wait_rows/2, wait_rows1/2, wait_val/2, collect_object/2 ]). -define(TIMEOUT, 5000). fold_by_id(#{pool := Pool} = Conn, UserFun, AccIn, Options) -> Headers = case proplists:get_value(docids, Options) of undefined -> [{<<"Content-Type">>, <<"application/json">>}]; Ids when is_list(Ids) -> [ {<<"Content-Type">>, <<"application/json">>} | [{<<"x-barrel-id-match">>, Id} || Id <- Ids] ] end, Url = barrel_httpc_lib:make_url(Conn, <<"docs">>, proplists:delete(docids, Options)), ReqOpts = [{async, once}, {pool, Pool}], WrapperFun = fun(Obj, Acc) -> % extract metadata. #{ <<"doc">> := Doc, <<"meta">> := Meta} = Obj, UserFun(Doc, Meta, Acc) end, case hackney:request(<<"Get">>, Url, Headers, <<>>, ReqOpts) of {ok, Ref} -> wait_fold_response(Ref, WrapperFun, AccIn); Error -> Error end. fold_by_path(#{pool := Pool}= Conn, Path, UserFun, AccIn, Options) when is_binary(Path) -> Url = barrel_httpc_lib:make_url(Conn, [<<"walk">>, Path], [{include_docs, true} |Options]), Headers = [{<<"Content-Type">>, <<"application/json">>}], ReqOpts = [{async, once}, {pool, Pool}], IncludeDoc = proplists:get_value(include_docs, Options, false), WrapperFun = fun (#{ <<"doc">> := Doc} = Obj1, Acc) -> Val = barrel_jsonpointer:get(Path, Doc), Obj2 = case IncludeDoc of true -> Obj1#{ <<"val">> => Val }; false -> maps:put(<<"val">>, Val, maps:remove(<<"doc">>, Obj1)) end, UserFun(Obj2, Acc); (Obj, Acc) -> UserFun(Obj, Acc) end, case hackney:request(<<"GET">>, Url, Headers, <<>>, ReqOpts) of {ok, Ref} -> error_logger:info_msg("wait resp on ~p~n", [Url]), wait_fold_response(Ref, WrapperFun, AccIn); Error -> Error end; fold_by_path(_Conn, _Path, _Fun, _AccIn, _Options) -> erlang:error(badarg). changes_since(#{pool := Pool}= Conn, Since, Fun, AccIn, Options) -> SinceBin = integer_to_binary(Since), Url = barrel_httpc_lib:make_url(Conn, <<"docs">>, [{<<"since">>, SinceBin} | Options]), Headers = [ {<<"Content-Type">>, <<"application/json">>}, {<<"A-IM">>, <<"Incremental feed">>} ], ReqOpts = [{async, once}, {pool, Pool}], case hackney:request(<<"GET">>, Url, Headers, <<>>, ReqOpts) of {ok, Ref} -> wait_fold_response(Ref, Fun, AccIn); Error -> Error end. wait_fold_response(Ref, Fun, AccIn) -> receive {hackney_response, Ref, {status, 200, _}} -> DecodeFun = jsx:decoder(?MODULE, [Fun, AccIn], [stream]), State = #{ref => Ref, decode_fun => DecodeFun, cb => Fun, acc => AccIn }, loop(State); {hackney_response, Ref, {status, 404, _}} -> {error, not_found}; {hackney_response, Ref, {status, Status, Reason}} -> {error, {http_error, Status, Reason}}; {hackney_response, Ref, {error, Reason}} -> {error, Reason} after ?TIMEOUT -> {error, timeout} end. loop(State = #{ ref := Ref}) -> ok = hackney:stream_next(Ref), receive {hackney_response, Ref, {headers, _Headers}} -> loop(State); {hackney_response, Ref, done} -> {error, bad_requet}; {hackney_response, Ref, Data} when is_binary(Data) -> decode_data(Data, State); {hackney_response, Ref, Error} -> Error after ?TIMEOUT -> {error, timeout} end. decode_data(Data, State = #{ref := Ref, decode_fun := DecodeFun}) -> try {incomplete, DecodeFun2} = DecodeFun(Data), try DecodeFun2(end_stream) of {done, Acc} -> _ = hackney:stop_async(Ref), ok = hackney:skip_body(Ref), {ok, Acc} catch error:badarg -> loop(State#{ decode_fun => DecodeFun2 }) end catch error:badarg -> exit(badarg) end. %%% json decoder %%% init([Fun, AccIn]) -> #{ cb => Fun, acc => AccIn, next => fun wait_rows/2, ctx => nil}. handle_event(end_json, #{ acc := Acc }) -> {done, Acc}; handle_event(Event, St = #{next := Fun}) -> Fun(Event, St). wait_rows(start_object, St) -> St; wait_rows(end_object, St) -> St; wait_rows({key, <<"docs">>}, St) -> St#{ next => fun wait_rows1/2 }; wait_rows({key, <<"changes">>}, St) -> St#{ next => fun wait_rows1/2 }; %% current changes api wait_rows({key, <<"count">>}, St) -> St#{ next => fun wait_val/2 }; wait_rows({key, <<"last_seq">>}, St) -> St#{ next => fun wait_val/2 }; %% current change api wait_rows(_Other, _) -> erlang:error(badarg). wait_val({_, _}, St) -> St#{ next => fun wait_rows/2 }. wait_rows1(start_array, St) -> St; wait_rows1(start_object, St) -> St#{ next => fun collect_object/2, ctx => [#{}] }; wait_rows1(end_array, St) -> St#{ next => fun wait_rows/2 }. collect_object(start_object, St = #{ctx := Ctx}) -> St#{ ctx => [#{} | Ctx] }; collect_object(end_object, St = #{ctx := [Obj, Key, Parent | Rest]}) when is_binary(Key) -> St#{ ctx => [ Parent#{ Key => Obj } | Rest ] }; collect_object(end_object, St = #{ctx := [Obj, List | Rest]}) when is_list(List) -> St#{ ctx => [ [Obj | List] | Rest ] }; collect_object(end_object, St = #{cb := Fun, acc := Acc, ctx := [Obj]}) when is_map(Obj) -> case Fun(Obj, Acc) of {ok, Acc2} -> St#{ acc => Acc2, next => fun wait_rows1/2, ctx => []}; stop -> throw({stop, Acc}); {stop, Acc2} -> throw({stop, Acc2}) end; collect_object(start_array, St = #{ctx := Ctx})-> St#{ ctx => [[] | Ctx]}; collect_object(end_array, St = #{ctx := [A, Key, Obj|Rest]}) when is_list(A), is_binary(Key) -> St#{ ctx => [Obj#{ Key => lists:reverse(A) } | Rest] }; collect_object({key, Key}, St = #{ctx := Ctx}) -> St#{ ctx => [Key | Ctx]}; collect_object({_, Val}, St = #{ctx := [List|Rest]}) when is_list(List) -> St#{ ctx => [ [Val | List] | Rest] }; collect_object({_, Val}, St = #{ctx := [Key, Obj |Rest]}) when is_map(Obj), is_binary(Key) -> St#{ ctx => [ Obj#{ Key => Val } | Rest] }. ================================================ FILE: apps/barrel_httpc/src/barrel_httpc_lib.erl ================================================ %%%------------------------------------------------------------------- %%% @author benoitc %%% @copyright (C) 2017, %%% @doc %%% %%% @end %%% Created : 17. Jan 2017 16:27 %%%------------------------------------------------------------------- -module(barrel_httpc_lib). -author("benoitc"). %% API -export([ to_hex/1, make_url/3, binary_join/2, to_binary/1 ]). to_hex([]) -> []; to_hex(Bin) when is_binary(Bin) -> << <<(to_digit(H)),(to_digit(L))>> || <> <= Bin >>; to_hex([H|T]) -> [to_digit(H div 16), to_digit(H rem 16) | to_hex(T)]. to_digit(N) when N < 10 -> $0 + N; to_digit(N) -> $a + N-10. -spec make_url(Conn, Path, Qs) -> Url when Conn :: barrel_httpc:conn(), Path :: binary() | [binary()], Qs :: list(), Url :: binary(). make_url(#{db_url := DbUrl}, Path, Qs) -> hackney_url:make_url(DbUrl, Path, Qs). to_binary(V) when is_binary(V) -> V; to_binary(V) when is_list(V) -> list_to_binary(V); to_binary(V) when is_atom(V) -> atom_to_binary(V, utf8); to_binary(V) when is_integer(V) -> integer_to_binary(V); to_binary(_) -> error(badarg). -spec binary_join([binary()], binary()) -> binary(). binary_join([], _Sep) -> <<>>; binary_join([Part], _Sep) -> to_binary(Part); binary_join([Head|Tail], Sep) -> lists:foldl( fun (Value, Acc) -> <> end, to_binary(Head), Tail ). ================================================ FILE: apps/barrel_httpc/src/barrel_httpc_sup.erl ================================================ %%%------------------------------------------------------------------- %% @doc barrel top level supervisor. %% @end %%%------------------------------------------------------------------- -module(barrel_httpc_sup). -behaviour(supervisor). %% API -export([start_link/0]). %% Supervisor callbacks -export([init/1]). -define(SERVER, ?MODULE). %%==================================================================== %% API functions %%==================================================================== start_link() -> supervisor:start_link({local, ?SERVER}, ?MODULE, []). %%==================================================================== %% Supervisor callbacks %%==================================================================== %% Child :: {Id,StartFunc,Restart,Shutdown,Type,Modules} init([]) -> {ok, { {one_for_all, 0, 1}, []} }. %%==================================================================== %% Internal functions %%==================================================================== ================================================ FILE: apps/barrel_httpc/src/barrel_jsonpointer.erl ================================================ %% Copyright 2016-2017, Benoit Chesneau %% %% Licensed under the Apache License, Version 2.0 (the "License"); you may not %% use this file except in compliance with the License. You may obtain a copy of %% the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT %% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the %% License for the specific language governing permissions and limitations under %% the License. %% @doc miscellaneous functions to manipulate JSONs %% %% TODO: this part can be optimized in rust or C if needed -module(barrel_jsonpointer). -export([decode_path/1]). -export([get/2]). decode_path(Path) when is_binary(Path) -> decode_path(Path, []); decode_path(Path) when is_list(Path) -> Path; decode_path(_) -> erlang:error(badarg). decode_path(<<>>, Acc) -> lists:reverse(Acc); decode_path(<< $~, $0, Rest/binary >>, [Current |Done]) -> decode_path(Rest, [ << Current/binary, $~ >> | Done ]); decode_path(<< $~, $1, Rest/binary >>, [Current |Done]) -> decode_path(Rest, [ << Current/binary, $/ >> | Done ]); decode_path(<< $/, Rest/binary >>, Acc) -> decode_path(Rest, [<<>> |Acc]); decode_path(<>, []) -> decode_path(Rest, [<< Codepoint/utf8 >>]); decode_path(<>, [Current|Done]) -> decode_path(Rest, [<< Current/binary, Codepoint/utf8 >> | Done]). get(Path, Doc) -> get_1(decode_path(Path), Doc). get_1([Key | Rest], Obj) when is_map(Obj) -> get_1(Rest, maps:get(Key, Obj)); get_1([BinInt | Rest], Obj) when is_list(Obj) -> Idx = binary_to_integer(BinInt) + 1, %% erlang lists start at 1 get_1(Rest, lists:nth(Idx, Obj)); get_1([Key], Obj) -> ToMatch = case jsx:is_json(Key) of true -> jsx:decode(Key); false -> Key end, if Obj =:= ToMatch -> null; true -> erlang:error(badarg) end; get_1([], Obj) -> Obj. -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). -define(doc, #{ <<"a">> => 1, <<"b">> => <<"2">>, <<"c">> => #{ <<"a">> => 1, <<"b">> => [<<"a">>, <<"b">>, <<"c">>], <<"c">> => #{ <<"a">> => 1} }, <<"d">> => [<<"a">>, <<"b">>, <<"c">>], <<"e">> => [#{<<"a">> => 1}, #{ <<"b">> => 2}] }). decode_path_test() -> ?assertEqual([<<"c">>, <<"a">>], decode_path(<<"c/a">>)), ?assertEqual([<<"c">>, <<"b">>, <<"0">>], decode_path(<<"c/b/0">>)), ?assertEqual([<<"c">>, <<"a">>], [<<"c">>, <<"a">>]), ?assertError(badarg, decode_path(1)). get_test() -> ?assertEqual(1, get(<<"a">>, ?doc)), ?assertEqual(1, get(<<"c/a">>, ?doc)), ?assertEqual(1, get(<<"c/c/a">>, ?doc)), ?assertEqual([<<"a">>, <<"b">>, <<"c">>], get(<<"c/b">>, ?doc)), ?assertEqual(<<"a">>, get(<<"c/b/0">>, ?doc)), ?assertEqual(<<"b">>, get(<<"c/b/1">>, ?doc)), ?assertEqual(1, get(<<"e/0/a">>, ?doc)), ?assertEqual(null, get(<<"a/1">>, ?doc)), ?assertError(badarg, get(<<"a/c">>, ?doc)). -endif. ================================================ FILE: apps/barrel_httpc/test/barrel_httpc_attachments_SUITE.erl ================================================ %% Copyright 2016, Benoit Chesneau %% %% Licensed under the Apache License, Version 2.0 (the "License"); you may not %% use this file except in compliance with the License. You may obtain a copy of %% the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT %% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the %% License for the specific language governing permissions and limitations under %% the License. -module(barrel_httpc_attachments_SUITE). -author("Benoit Chesneau"). -define(DB_URL,<<"http://localhost:7080/dbs/testdb">>). -define(DB,<<"testdb">>). %% API -export([ all/0, init_per_suite/1, end_per_suite/1, init_per_testcase/2, end_per_testcase/2 ]). -export([ attachment_doc/1, binary_attachment/1, atomic_attachment/1, atomic_erlang_term_attachment/1, attachment_parsing/1 ]). all() -> [ attachment_doc, binary_attachment, atomic_attachment, atomic_erlang_term_attachment, attachment_parsing ]. init_per_suite(Config) -> {ok, _} = application:ensure_all_started(barrel_rest), Config. init_per_testcase(_, Config) -> _ = barrel_httpc:create_database(?DB_URL), {ok, Conn} = barrel_httpc:connect(?DB_URL), [{db_url, Conn}, {db, ?DB} | Config]. end_per_testcase(_, _Config) -> _ = barrel_httpc:delete_database(?DB_URL), ok. end_per_suite(Config) -> _ = application:stop(barrel_rest), Config. db(Config) -> proplists:get_value(db_url, Config). localdb(Config) -> proplists:get_value(db, Config). attachment_doc(Config) -> DocId = <<"a">>, Doc = #{ <<"id">> => DocId, <<"v">> => 1}, {ok, <<"a">>, R1} = barrel_httpc:post(db(Config) , Doc, []), AttId = <<"myattachement">>, AttDescription = #{ <<"id">> => AttId, <<"content-type">> => <<"image/png">>, <<"link">> => <<"http://somehost.com/cat.png">> }, {ok, DocId, R2} = barrel_httpc_attachments:attach(db(Config) , DocId, AttDescription, [{rev, R1}]), {ok, Doc, _} = barrel_httpc:get(db(Config), DocId, []), {ok, AttDescription} = barrel_httpc_attachments:get_attachment(db(Config) , DocId, <<"myattachement">>, []), [AttDescription] = barrel_httpc_attachments:attachments(db(Config) , DocId, []), AttDescription2 = AttDescription#{<<"link">> => <<"http://anotherhost.com/panther.png">>}, {error, attachment_conflict} = barrel_httpc_attachments:attach(db(Config) , DocId, AttDescription2, [{rev, R2}]), {ok, DocId, R3} = barrel_httpc_attachments:replace_attachment(db(Config) , DocId, AttId, AttDescription2, [{rev, R2}]), [AttDescription2] = barrel_httpc_attachments:attachments(db(Config) , DocId, []), {ok, DocId, _} = barrel_httpc_attachments:delete_attachment(db(Config) , DocId, AttId, [{rev, R3}]), [] = barrel_httpc_attachments:attachments(db(Config) , DocId, []), ok. binary_attachment(Config) -> DocId = <<"a">>, Doc = #{ <<"id">> => DocId, <<"v">> => 1}, {ok, <<"a">>, R1} = barrel_httpc:post(db(Config) , Doc, []), AttId = <<"myattachement">>, AttDescription = #{ <<"id">> => AttId, <<"content-type">> => <<"image/png">> }, Blob = <<"blobdata">>, {ok, DocId, R2} = barrel_httpc_attachments:attach(db(Config) , DocId, AttDescription, Blob, [{rev, R1}]), {ok, Blob} = barrel_httpc_attachments:get_attachment_binary(db(Config) , DocId, AttId, [{rev, R2}]), Blob2 = <<"anotherblobdata">>, {ok, DocId, R3} = barrel_httpc_attachments:replace_attachment_binary(db(Config) , DocId, AttId, Blob2, [{rev, R2}]), {ok, Blob2} = barrel_httpc_attachments:get_attachment_binary(db(Config) , DocId, AttId, [{rev, R3}]), ok. atomic_attachment(Config) -> DocId = <<"a">>, Doc = #{ <<"id">> => DocId, <<"v">> => 1}, AttId = <<"myattachement">>, Blob = <<"blobdata">>, Attachments = [#{<<"id">> => AttId, <<"blob">> => Blob}, #{<<"id">> => <<"2">>, <<"blob">> => <<"2">>}], %% store a document with attachments {ok, <<"a">>, R1} = barrel_httpc:post(db(Config), Doc, Attachments, []), %% the document is stored with attachments in prop _attachments {ok, StoredDoc, _} = barrel:get(localdb(Config), DocId, #{}), B64 = base64:encode(Blob), #{<<"_attachments">> := [#{<<"id">> := AttId, <<"content-type">> := <<"application/octet-stream">>, <<"content-length">> := 8, <<"blob">> := B64}|_]} = StoredDoc, %% httpc:get does not return attachments by defautl {ok, Doc, #{<<"rev">> := R1}} = barrel_httpc:get(db(Config), DocId, []), %% ask httpc:get to retrive the attachments with options {attachments, all} {ok, Doc, [A1,A2], _} = barrel_httpc:get(db(Config), DocId, [{attachments, all}]), #{<<"id">> := AttId, <<"content-type">> := <<"application/octet-stream">>, <<"content-length">> := 8, <<"blob">> := Blob} = A1, #{<<"id">> := <<"2">>, <<"content-type">> := <<"application/octet-stream">>, <<"content-length">> := 1, <<"blob">> := <<"2">>} = A2, %% update the attachments Attachments2 = [#{<<"id">> => AttId, <<"blob">> => Blob}, #{<<"id">> => <<"2">>, <<"blob">> => <<"3">>}], {ok, <<"a">>, _R2} = barrel_httpc:put(db(Config), Doc, Attachments2, []), {ok, Doc, [A1,A3], _} = barrel_httpc:get(db(Config), DocId, [{attachments, all}]), #{<<"id">> := <<"2">>, <<"content-type">> := <<"application/octet-stream">>, <<"content-length">> := 1, <<"blob">> := <<"3">>} = A3, %% delete all attachments {ok, <<"a">>, _} = barrel_httpc:put(db(Config), Doc, [], []), {ok, Doc, [], _} = barrel_httpc:get(db(Config), DocId, [{attachments, all}]), ok. atomic_erlang_term_attachment(Config) -> DocId = <<"test_document">>, Doc = #{<<"id">> => DocId, <<"v">> => 1}, AttId = <<"myattachement">>, Term = {atuple, [a, list], #{a => "map", <<"with">> => <<"binary">>}}, %% bad content type BadContentType = [#{<<"id">> => AttId, <<"content-type">> => <<"application/erlang">>, <<"blob">> => <<"somebinary">>}], {error, {erlang_term_expected, AttId}} = barrel_httpc:post(db(Config), Doc, BadContentType, []), %% content-type not given for erlang term WithoutContentType = [#{<<"id">> => AttId, <<"blob">> => Term}], {ok, DocId, _} = barrel_httpc:post(db(Config), Doc, WithoutContentType, []), %% retrieve decoded attachment {ok, Doc, [A], _} = barrel_httpc:get(db(Config), DocId, [{attachments, all}]), lager:warning("Got Document ~p", [A]), #{<<"id">> := AttId, <<"content-type">> := <<"application/erlang">>, <<"content-length">> := Len, <<"blob">> := Term} = A, true = lists:member(Len, [60,64]), ok. attachment_parsing(Config) -> DocId = <<"a">>, Doc = #{ <<"id">> => DocId, <<"v">> => 1}, AttId = <<"myattachement">>, Blob = <<"blobdata">>, Attachments = [#{<<"id">> => AttId, <<"blob">> => Blob}], {ok, <<"a">>, R1} = barrel_httpc:post(db(Config), Doc, Attachments, []), {ok, Doc, #{<<"rev">> := R1}} = barrel_httpc:get(db(Config), DocId, []), {ok, NoParsing, #{<<"rev">> := R1}} = barrel_httpc:get(db(Config), DocId, [{attachments_parsing, false}]), #{<<"_attachments">> := EncodedAttachments, <<"id">> := DocId, <<"v">> := 1} = NoParsing, [#{<<"id">> := AttId}] = EncodedAttachments, ok. ================================================ FILE: apps/barrel_httpc/test/barrel_httpc_changes_test_SUITE.erl ================================================ %% Copyright 2017, Benoit Chesneau %% %% Licensed under the Apache License, Version 2.0 (the "License"); you may not %% use this file except in compliance with the License. You may obtain a copy of %% the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT %% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the %% License for the specific language governing permissions and limitations under %% the License. -module(barrel_httpc_changes_test_SUITE). -author("benoitc"). -define(DB_URL,<<"http://localhost:7080/dbs/testdb">>). -define(SAMPLE_SIZE, 100). -export([ collect_change/1, include_doc/1, collect_changes/1, changes_feed_callback/1, restart_when_server_timeout/1, heartbeat_and_timeout/1, heartbeat_collect_change/1, multiple_put/1 ]). -export([ all/0, init_per_suite/1, end_per_suite/1, init_per_testcase/2, end_per_testcase/2 ]). all() -> [ collect_change, include_doc, collect_changes, changes_feed_callback, heartbeat_collect_change, heartbeat_and_timeout, multiple_put, restart_when_server_timeout ]. init_per_suite(Config) -> {ok, _} = application:ensure_all_started(barrel_rest), Config. init_per_testcase(_, Config) -> ok = barrel_httpc:create_database(?DB_URL), {ok, Conn} = barrel_httpc:connect(?DB_URL), [{db, Conn} | Config]. end_per_testcase(_, _Config) -> ok = barrel_httpc:delete_database(?DB_URL), ok. end_per_suite(Config) -> _ = application:stop(barrel_rest), Config. db(Config) -> proplists:get_value(db, Config). collect_change(Config) -> {ok, Pid} = barrel_httpc_changes:start_link(db(Config), #{since => 0, mode => sse}), [] = barrel_httpc_changes:changes(Pid), Doc = #{ <<"id">> => <<"aa">>, <<"v">> => 1}, {ok, <<"aa">>, _RevId} = barrel_httpc:post(db(Config), Doc, []), timer:sleep(100), [#{ <<"seq">> := 1, <<"id">> := <<"aa">>}] = barrel_httpc_changes:changes(Pid), [] = barrel_httpc_changes:changes(Pid), ok = barrel_httpc_changes:stop(Pid). include_doc(Config) -> {ok, Pid} = barrel_httpc_changes:start_link(db(Config), #{since => 0, mode => sse, include_doc => true}), [] = barrel_httpc_changes:changes(Pid), Doc = #{ <<"id">> => <<"aa">>, <<"v">> => 1}, {ok, <<"aa">>, _RevId} = barrel_httpc:post(db(Config), Doc, []), timer:sleep(100), [#{ <<"seq">> := 1, <<"id">> := <<"aa">>, <<"doc">> := Doc2}] = barrel_httpc_changes:changes(Pid), #{ <<"id">> := <<"aa">>, <<"v">> := 1 } = Doc2, [] = barrel_httpc_changes:changes(Pid), ok = barrel_httpc_changes:stop(Pid). collect_changes(Config) -> {ok, Pid} = barrel_httpc_changes:start_link(db(Config), #{since => 0, mode => sse}), [] = barrel_httpc_changes:changes(Pid), Doc = #{ <<"id">> => <<"aa">>, <<"v">> => 1}, {ok, <<"aa">>, _} = barrel_httpc:post(db(Config), Doc, []), timer:sleep(100), [#{ <<"seq">> := 1, <<"id">> := <<"aa">>}] = barrel_httpc_changes:changes(Pid), [] = barrel_httpc_changes:changes(Pid), Doc2 = #{ <<"id">> => <<"bb">>, <<"v">> => 1}, {ok, <<"bb">>, _} = barrel_httpc:post(db(Config), Doc2, []), {ok, _, _} = barrel_httpc:get(db(Config), <<"bb">>, []), timer:sleep(100), [#{ <<"seq">> := 2, <<"id">> := <<"bb">>}] = barrel_httpc_changes:changes(Pid), [] = barrel_httpc_changes:changes(Pid), Doc3 = #{ <<"id">> => <<"cc">>, <<"v">> => 1}, Doc4 = #{ <<"id">> => <<"dd">>, <<"v">> => 1}, {ok, <<"cc">>, _} = barrel_httpc:post(db(Config), Doc3, []), {ok, <<"dd">>, _} = barrel_httpc:post(db(Config), Doc4, []), {ok, _, _} = barrel_httpc:get(db(Config), <<"cc">>, []), {ok, _, _} = barrel_httpc:get(db(Config), <<"dd">>, []), timer:sleep(100), [ #{ <<"seq">> := 3, <<"id">> := <<"cc">>}, #{ <<"seq">> := 4, <<"id">> := <<"dd">>} ] = barrel_httpc_changes:changes(Pid), ok = barrel_httpc_changes:stop(Pid). changes_feed_callback(Config) -> Self = self(), Callback = fun(Change) -> Self ! {change, Change} end, Options = #{since => 0, mode => sse, changes_cb => Callback }, {ok, Pid} = barrel_httpc_changes:start_link(db(Config), Options), Doc1 = #{ <<"id">> => <<"aa">>, <<"v">> => 1}, Doc2 = #{ <<"id">> => <<"bb">>, <<"v">> => 1}, {ok, <<"aa">>, _} = barrel_httpc:post(db(Config), Doc1, []), {ok, <<"bb">>, _} = barrel_httpc:post(db(Config), Doc2, []), {ok, _, _} = barrel_httpc:get(db(Config), <<"aa">>, []), {ok, _, _} = barrel_httpc:get(db(Config), <<"bb">>, []), timer:sleep(100), [ #{ <<"seq">> := 1, <<"id">> := <<"aa">>}, #{ <<"seq">> := 2, <<"id">> := <<"bb">>} ] = collect_changes(2, queue:new()), ok = barrel_httpc_changes:stop(Pid). restart_when_server_timeout(Config) -> Self = self(), Callback = fun(Change) -> Self ! {change, Change} end, Val = <<"AACC">>, Options = #{since => 0, mode => sse, changes_cb => Callback, retry_timeout=>200}, {ok, Pid} = barrel_httpc_changes:start_link(db(Config), Options), Doc1 = #{ <<"id">> => Val, <<"v">> => 1}, Doc2 = #{ <<"id">> => <<"bb">>, <<"v">> => 1}, {ok, Val, _} = barrel_httpc:post(db(Config), Doc1, []), SLEEP_TIME=250, ok = application:stop(barrel_rest), timer:sleep(SLEEP_TIME), ok = application:start(barrel_rest), {ok, <<"bb">>, _} = barrel_httpc:post(db(Config), Doc2, []), receive {change, #{ <<"seq">> := 2, <<"id">> := <<"bb">>}} -> ok after 5000 -> lager:notice("Seq 2 timeout",[]), throw(timeout) end, receive {change, #{ <<"seq">> := 1, <<"id">> := Val}} -> ok; _E -> lager:notice("Recived 1 ~p",[_E]) after 5000 -> lager:notice("Seq 1 timeout",[]), throw(timeout) end, %% ok = case collect_changes(2, queue:new()) of %% [ %% #{ <<"seq">> := 1, <<"id">> := Val}, %% #{ <<"seq">> := 2, <<"id">> := <<"bb">>} %% ] -> ok; %% _E -> %% lager:info("Returned ~p~n",[_E]), %% false %% end, ok = application:stop(barrel_rest), {error, timeout} = collect_changes(1, queue:new()), ok = barrel_httpc_changes:stop(Pid), ok = application:start(barrel_rest), ok. heartbeat_collect_change(Config) -> Options = #{since => 0, heartbeat => 100, mode => sse, retry_timeout => 500}, {ok, Pid} = barrel_httpc_changes:start_link(db(Config), Options), timer:sleep(500), [] = barrel_httpc_changes:changes(Pid), Doc = #{ <<"id">> => <<"aa">>, <<"v">> => 1}, {ok, <<"aa">>, _RevId} = barrel_httpc:post(db(Config), Doc, []), timer:sleep(100), [#{ <<"seq">> := 1, <<"id">> := <<"aa">>}] = barrel_httpc_changes:changes(Pid), [] = barrel_httpc_changes:changes(Pid), ok = barrel_httpc_changes:stop(Pid). heartbeat_and_timeout(Config) -> process_flag(trap_exit, true), %% httpc will timeout before receiving the heartbeat Options1 = #{since => 0, timeout => 50, heartbeat => 100, mode => sse, retry_timeout => 500 }, {ok, Pid1} = barrel_httpc_changes:start_link(db(Config), Options1), ok = receive {'EXIT', Pid1, timeout} -> ok; Unexpected -> {unexpected, Unexpected} after 2000 -> {error, test_timeout} end, %% timeout is larger than heartbeat. We will keep receiving changes. Options2 = #{since => 0, timeout => 200, heartbeat => 100, mode => sse, retry_timeout => 1000 }, {ok, Pid2} = barrel_httpc_changes:start_link(db(Config), Options2), [] = barrel_httpc_changes:changes(Pid2), Doc = #{ <<"id">> => <<"aa">>, <<"v">> => 1}, {ok, <<"aa">>, _RevId} = barrel_httpc:post(db(Config), Doc, []), timer:sleep(100), [#{ <<"seq">> := 1, <<"id">> := <<"aa">>}] = barrel_httpc_changes:changes(Pid2), [] = barrel_httpc_changes:changes(Pid2), %% httpc did not timeout ok = receive {'EXIT', Pid1, timeout} -> {error, timeout_received}; Other -> {unexpected, Other} after 0 -> ok end, ok = barrel_httpc_changes:stop(Pid2), ok. multiple_put(Config) -> Self = self(), timer:sleep(500), lager:notice("Config = ~p.~n~n~n", [Config]), %% spawn a change listener spawn( fun() -> ChangePid = self(), Callback = fun(Change) -> ChangePid ! {change, Change} end, Options = #{since => 0, mode => sse, changes_cb => Callback }, {ok, _Pid} = barrel_httpc_changes:start_link(db(Config), Options), Changes = collect_changes(?SAMPLE_SIZE, queue:new()), Self ! {changes, Changes} end ), %% write docs Pids = lists:foldl( fun(I, Acc) -> DocId = << "doc", (integer_to_binary(I))/binary >>, Doc = #{ <<"id">> => DocId, <<"val">> => I}, Pid = spawn_link( fun() -> {ok, DocId, _} = barrel_httpc:post(db(Config), Doc, []), Self ! {ok, self()}, timer:sleep(200) end ), [Pid | Acc] end, [], lists:seq(1, ?SAMPLE_SIZE) ), ?SAMPLE_SIZE = length(Pids), ok = wait_pids(Pids), #{ <<"docs_count">> := ?SAMPLE_SIZE } = barrel_httpc:database_infos(?DB_URL), receive {changes, Changes} -> case length(Changes) of ?SAMPLE_SIZE -> ok; Other -> ct:fail("bad changes count=~p",[Other]) end end, ok. collect_changes(0, Q) -> queue:to_list(Q); collect_changes(I, Q) -> receive {change, Change} -> collect_changes(I-1, queue:in(Change, Q)) after 5000 -> lager:notice("Queue on Timeout ~p", [Q]), {error, timeout} %collect_changes(0, queue:in({error, timeout}, Q)) end. wait_pids([]) -> ok; wait_pids(Pids) -> receive {ok, Pid} -> wait_pids(Pids -- [Pid]) after 5000 -> {error, receive_pids} end. ================================================ FILE: apps/barrel_httpc/test/barrel_httpc_test_SUITE.erl ================================================ %% Copyright 2017, Benoit Chesneau %% %% Licensed under the Apache License, Version 2.0 (the "License"); you may not %% use this file except in compliance with the License. You may obtain a copy of %% the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT %% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the %% License for the specific language governing permissions and limitations under %% the License. %% Created by benoitc on 03/09/16. -module(barrel_httpc_test_SUITE). -author("benoitc"). -define(DB_URL,<<"http://localhost:7080/dbs/testdb">>). -define(COUNT, 150). %% API -export([ all/0, init_per_suite/1, end_per_suite/1, init_per_testcase/2, end_per_testcase/2 ]). -export([ db_ops/1, basic_op/1, update_doc/1, delete_doc_without_revision/1, update_with/1, async_update/1, bad_doc/1, create_doc/1, get_revisions/1, put_rev/1, multi_get/1, write_batch/1, write_batch_with_attachment/1, fold_by_id/1, order_by_key/1, multiple_post/1, multiple_get/1, multiple_delete/1, change_since/1, change_deleted/1, change_since_include_doc/1, change_since_many/1, revsdiff/1, system_docs/1 ]). all() -> [ db_ops, basic_op, update_doc, delete_doc_without_revision, update_with, async_update, bad_doc, create_doc, get_revisions, put_rev, multi_get, write_batch, write_batch_with_attachment, fold_by_id, order_by_key, multiple_post, multiple_get, multiple_delete, change_since, change_deleted, change_since_include_doc, change_since_many, revsdiff ]. init_per_suite(Config) -> {ok, _} = application:ensure_all_started(barrel_rest), Config. init_per_testcase(_, Config) -> _ = barrel:create_database(#{ <<"database_id">> => <<"testdb">> }), _ = barrel:create_database(#{ <<"database_id">> => <<"source">> }), {ok, Conn} = barrel_httpc:connect(?DB_URL), [{db, Conn} | Config]. end_per_testcase(_, _Config) -> ok = barrel:delete_database(<<"testdb">>), ok = barrel:delete_database(<<"source">>), ok. end_per_suite(Config) -> _ = application:stop(barrel_rest), Config. db(Config) -> proplists:get_value(db, Config). db_ops(_Config) -> {error, not_found} = barrel_httpc:connect(<<"http://localhost:7080/dbs/test-nofound">>), [<<"source">>, <<"testdb">>] = barrel_httpc:database_names(<<"http://localhost:7080">>), {error, not_found} = barrel_httpc:connect(<<"http://localhost:7080/dbs/testdb2">>), ok = barrel_httpc:create_database(<<"http://localhost:7080/dbs/testdb2">>), [<<"source">>, <<"testdb">>, <<"testdb2">>] = barrel_httpc:database_names(<<"http://localhost:7080">>), {ok, _Conn} = barrel_httpc:connect(<<"http://localhost:7080/dbs/testdb2">>), ok = barrel_httpc:delete_database(<<"http://localhost:7080/dbs/testdb2">>), {error, not_found} = barrel_httpc:connect(<<"http://localhost:7080/dbs/testdb2">>), [<<"source">>, <<"testdb">>] = barrel_httpc:database_names(<<"http://localhost:7080">>), DbUrl = <<"http://localhost:7080/dbs/testdb2">>, {ok, DbUrl} = barrel_httpc:create_database( <<"http://localhost:7080">>, #{ <<"database_id">> => <<"testdb2">>} ), [<<"source">>, <<"testdb">>, <<"testdb2">>] = barrel_httpc:database_names(<<"http://localhost:7080">>), ok = barrel_httpc:delete_database(<<"http://localhost:7080/dbs/testdb2">>), ok. basic_op(Config) -> {error, not_found} = barrel_httpc:get(db(Config), <<"a">>, []), Doc = #{ <<"id">> => <<"a">>, <<"v">> => 1}, {ok, <<"a">>, RevId} = barrel_httpc:post(db(Config), Doc, []), {ok, Doc, #{ <<"rev">> := RevId }} = barrel_httpc:get(db(Config), <<"a">>, []), {ok, <<"a">>, _RevId2} = barrel_httpc:delete(db(Config), <<"a">>, [{rev, RevId}]), {error, not_found} = barrel_httpc:get(db(Config), <<"a">>, []). update_doc(Config) -> Doc = #{ <<"id">> => <<"a">>, <<"v">> => 1}, {error, not_found} = barrel_httpc:put(db(Config), Doc, []), {ok, <<"a">>, RevId} = barrel_httpc:post(db(Config), Doc, []), {ok, Doc, #{ <<"rev">> := RevId }} = barrel_httpc:get(db(Config), <<"a">>, []), Doc2 = Doc#{ <<"v">> => 2}, {ok, <<"a">>, RevId2} = barrel_httpc:put(db(Config), Doc2, [{rev, RevId}]), true = (RevId =/= RevId2), {ok, Doc2, #{ <<"rev">> := RevId2 }} = barrel_httpc:get(db(Config), <<"a">>, []), {ok, <<"a">>, _RevId2} = barrel_httpc:delete(db(Config), <<"a">>, [{rev, RevId2}]), {error, not_found} = barrel_httpc:get(db(Config), <<"a">>, []), {ok, <<"a">>, _RevId3} = barrel_httpc:post(db(Config), Doc, []). delete_doc_without_revision(Config) -> Doc = #{ <<"id">> => <<"a">>, <<"v">> => 1}, {error, not_found} = barrel_httpc:get(db(Config), <<"a">>, []), {ok, <<"a">>, _RevId} = barrel_httpc:post(db(Config), Doc, []), {ok, Doc, _Meta} = barrel_httpc:get(db(Config), <<"a">>, []), {ok, _, _} = barrel_httpc:delete(db(Config), <<"a">>, []), {error, not_found} = barrel_httpc:get(db(Config), <<"a">>, []). update_with(Config) -> Doc = #{ <<"id">> => <<"a">>, <<"v">> => 1}, {ok, <<"a">>, RevId} = barrel_httpc:post(db(Config), Doc, []), {ok, Doc, #{ <<"rev">> := RevId }} = barrel_httpc:get(db(Config), <<"a">>, []), {ok, <<"a">>, RevId2} = barrel_httpc:update_with( db(Config), <<"a">>, fun(Doc1, []) -> Doc1#{ <<"v">> => 2} end, [] ), true = (RevId =/= RevId2), {ok, Doc2, #{ <<"rev">> := RevId2 }} = barrel_httpc:get(db(Config), <<"a">>, []), #{ <<"id">> := <<"a">>, <<"v">> := 2} = Doc2. async_update(Config) -> Doc = #{ <<"id">> => <<"a">>, <<"v">> => 1}, ok= barrel_httpc:post(db(Config), Doc, [{async, true}]), timer:sleep(200), {ok, #{ <<"id">> := <<"a">>, <<"v">> := 1}, #{ <<"rev">> := RevId } } = barrel_httpc:get(db(Config), <<"a">>, []), ok= barrel_httpc:put(db(Config), Doc#{ <<"v">> => 2 }, [{async, true}, {rev, RevId}]), timer:sleep(400), {ok, #{ <<"id">> := <<"a">>, <<"v">> := 2 }, _ } = barrel:get(<<"testdb">>, <<"a">>, #{}). bad_doc(Config) -> Doc = #{ <<"v">> => 1}, try barrel_httpc:put(db(Config), Doc, []) catch error:{bad_doc, invalid_docid} -> ok end. create_doc(Config) -> Doc = #{<<"v">> => 1}, {ok, DocId, _RevId} = barrel_httpc:post(db(Config), Doc, []), CreatedDoc = Doc#{ <<"id">> => DocId }, {ok, CreatedDoc, _} = barrel_httpc:get(db(Config), DocId, []), {error, conflict} = barrel_httpc:post(db(Config), CreatedDoc, []), Doc2 = #{<<"id">> => <<"b">>, <<"v">> => 1}, {ok, <<"b">>, _RevId2} = barrel_httpc:post(db(Config), Doc2, []). get_revisions(Config) -> Doc = #{<<"v">> => 1}, {ok, DocId, RevId} = barrel_httpc:post(db(Config), Doc, []), {ok, Doc2, _Meta} = barrel_httpc:get(db(Config), DocId, []), Doc3 = Doc2#{ v => 2}, {ok, DocId, RevId2} = barrel_httpc:put(db(Config), Doc3, [{rev, RevId}]), {ok, Doc4, _} = barrel_httpc:get(db(Config), DocId, [{history, true}]), Revisions = parse_revisions(Doc4), Revisions == [RevId2, RevId]. put_rev(Config) -> Doc = #{<<"v">> => 1}, {ok, DocId, RevId} = barrel_httpc:post(db(Config), Doc, []), {ok, Doc2, _} = barrel_httpc:get(db(Config), DocId, []), Doc3 = Doc2#{ <<"v">> => 2}, {ok, DocId, RevId2} = barrel_httpc:put(db(Config), Doc3, []), Doc4_0 = Doc2#{ <<"v">> => 3 }, {Pos, _} = parse_revision(RevId), NewRev = revid(Pos +1, RevId, Doc4_0), Doc4 = Doc4_0#{<<"_rev">> => NewRev}, History = [NewRev, RevId], Deleted = false, {ok, DocId, _RevId3} = barrel_httpc:put_rev(db(Config), Doc4, History, Deleted, []), {ok, Doc5, _} = barrel_httpc:get(db(Config), DocId, [{history, true}]), Revisions = parse_revisions(Doc5), Revisions == [RevId2, RevId]. multi_get(Config) -> %% create some docs Kvs = [{<<"a">>, 1}, {<<"b">>, 2}, {<<"c">>, 3}], Docs = [#{ <<"id">> => K, <<"v">> => V} || {K,V} <- Kvs], [ {ok,_,_} = barrel_httpc:post(db(Config), D, []) || D <- Docs ], Mget = [<<"a">>, <<"c">>], %% a fun to parse the results %% the parameter is the same format as the regular get function output Fun=fun(Doc, Meta, Acc) -> #{<<"id">> := DocId} = Doc, #{<<"rev">> := RevId} = Meta, [#{<<"id">> => DocId, <<"rev">> => RevId, <<"doc">> => Doc }|Acc] end, [] = barrel_httpc:multi_get(db(Config), Fun, [], [], []), %% let's process it Results = barrel_httpc:multi_get(db(Config), Fun, [], Mget, []), %% check results [#{<<"doc">> := #{<<"id">> := <<"a">>, <<"v">> := 1}, <<"id">> := <<"a">>, <<"rev">> := _}, #{<<"doc">> := #{<<"id">> := <<"c">>, <<"v">> := 3}}] = lists:reverse(Results). revsdiff(Config) -> Doc = #{ <<"id">> => <<"revsdiff">>, <<"v">> => 1}, {ok, <<"revsdiff">>, RevId} = barrel_httpc:post(db(Config), Doc, []), Doc2 = Doc#{ <<"v">> => 2}, {ok, <<"revsdiff">>, _RevId2} = barrel_httpc:put(db(Config), Doc2, [{rev, RevId}]), {ok, [<<"1-missing">>], []} = barrel_httpc:revsdiff(db(Config), <<"revsdiff">>, [<<"1-missing">>]), ok. write_batch(Config) -> %% create resources D1 = #{<<"id">> => <<"a">>, <<"v">> => 1}, D2 = #{<<"id">> => <<"b">>, <<"v">> => 1}, D3 = #{<<"id">> => <<"c">>, <<"v">> => 1}, D4 = #{<<"id">> => <<"d">>, <<"v">> => 1}, {ok, _, Rev1_1} = barrel_httpc:post(db(Config), D1, []), {ok, _, Rev3_1} = barrel_httpc:post(db(Config), D3, []), OPs = [ { put, D1#{ <<"v">> => 2 }, Rev1_1}, { post, D2, false}, { delete, <<"c">>, Rev3_1}, { put, D4, <<>>} ], {ok, #{ <<"v">> := 1}, _} = barrel_httpc:get(db(Config), <<"a">>, []), {error, not_found} = barrel_httpc:get(db(Config), <<"b">>, []), {ok, #{ <<"v">> := 1}, _} = barrel_httpc:get(db(Config), <<"c">>, []), Results = barrel_httpc:write_batch(db(Config), OPs, []), true = is_list(Results), [ {ok, <<"a">>, _}, {ok, <<"b">>, _}, {ok, <<"c">>, _}, {error, not_found} ] = Results, {ok, #{ <<"v">> := 2}, _} = barrel_httpc:get(db(Config), <<"a">>, []), {ok, #{ <<"v">> := 1}, _} = barrel_httpc:get(db(Config), <<"b">>, []), {error, not_found} = barrel_httpc:get(db(Config), <<"c">>, []). write_batch_with_attachment(Config) -> %% create resources D1 = #{<<"id">> => <<"a">>, <<"v">> => 1}, D2 = #{<<"id">> => <<"b">>, <<"v">> => 1}, Att1 = #{ <<"id">> => <<"att_a">>, <<"blob">> => <<"hello a">>}, Att2 = #{ <<"id">> => <<"att_b">>, <<"blob">> => <<"hello b">>}, %% store d1 and check db state {ok, _, Rev1_1} = barrel_httpc:post(db(Config), D1, []), {ok, D1, [], _} = barrel_httpc:get(db(Config), <<"a">>, [{attachments, all}]), {error, not_found} = barrel_httpc:get(db(Config), <<"b">>, []), %% write batch OPs = [ {put, D1, [Att1], Rev1_1}, {post, D2, [Att2]} ], Results = barrel_httpc:write_batch(db(Config), OPs, []), true = is_list(Results), [ {ok, <<"a">>, _}, {ok, <<"b">>, _} ] = Results, {ok, D1, [#{<<"id">> := <<"att_a">>, <<"blob">> := <<"hello a">>}], _} = barrel_httpc:get(db(Config), <<"a">>, [{attachments, all}]), {ok, D2, [#{<<"id">> := <<"att_b">>, <<"blob">> := <<"hello b">>}], _} = barrel_httpc:get(db(Config), <<"b">>, [{attachments, all}]). fold_by_id(Config) -> Doc = #{ <<"id">> => <<"a">>, <<"v">> => 1}, {ok, <<"a">>, _RevId} = barrel_httpc:post(db(Config), Doc, []), Doc2 = #{ <<"id">> => <<"b">>, <<"v">> => 1}, {ok, <<"b">>, _RevId2} = barrel_httpc:post(db(Config), Doc2, []), Doc3 = #{ <<"id">> => <<"c">>, <<"v">> => 1}, {ok, <<"c">>, _RevId3} = barrel_httpc:post(db(Config), Doc3, []), Fun = fun (#{ <<"id">> := DocId}, _Meta, Acc1) -> {ok, [DocId | Acc1]} end, {ok, Acc} = barrel_httpc:fold_by_id(db(Config), Fun, [], []), [<<"c">>, <<"b">>, <<"a">>] = Acc, {ok, Acc2} = barrel_httpc:fold_by_id(db(Config), Fun, [], [{lt, <<"b">>}]), [<<"a">>] = Acc2, {ok, Acc3} = barrel_httpc:fold_by_id(db(Config), Fun, [], [{lte, <<"b">>}]), [<<"b">>, <<"a">>] = Acc3, {ok, Acc4} = barrel_httpc:fold_by_id(db(Config), Fun, [], [{gte, <<"b">>}]), [<<"c">>, <<"b">>] = Acc4, {ok, Acc5} = barrel_httpc:fold_by_id(db(Config), Fun, [], [{gt, <<"b">>}]), [<<"c">>] = Acc5, ok. order_by_key(Config) -> Doc = #{ <<"id">> => <<"AndersenFamily">>, <<"lastName">> => <<"Andersen">>, <<"parents">> => [ #{ <<"firstName">> => <<"Thomas">> }, #{ <<"firstName">> => <<"Mary Kay">>} ], <<"children">> => [ #{ <<"firstName">> => <<"Henriette Thaulow">>, <<"gender">> => <<"female">>, <<"grade">> => 5, <<"pets">> => [#{ <<"givenName">> => <<"Fluffy">> }] } ], <<"address">> => #{ <<"state">> => <<"WA">>, <<"county">> => <<"King">>, <<"city">> => <<"seattle">> }, <<"creationDate">> => 1431620472, <<"isRegistered">> => true }, {ok, <<"AndersenFamily">>, _Rev} = barrel_httpc:post(db(Config), Doc, []), timer:sleep(400), {ok, Doc1, _} = barrel_httpc:get(db(Config), <<"AndersenFamily">>, []), Fun = fun(Obj, Acc) -> {ok, [Obj| Acc]} end, {ok, [#{<<"id">> := <<"AndersenFamily">>, <<"val">> := <<"AndersenFamily">>}]} = barrel_httpc:fold_by_path(db(Config), <<"id">>, Fun, [], []), {ok, [Obj]} = barrel_httpc:fold_by_path(db(Config), <<"id">>, Fun, [], [{include_docs, true}] ), #{<<"doc">> := Doc1} = Obj, ok. multiple_post(Config) -> Self = self(), Pids = lists:foldl( fun(I, Acc) -> DocId = << "doc", (integer_to_binary(I))/binary >>, Doc = #{ <<"id">> => DocId, <<"val">> => I}, Pid = spawn_link( fun() -> {ok, DocId, _} = barrel_httpc:post(db(Config), Doc, []), Self ! {ok, self()} end ), [Pid | Acc] end, [], lists:seq(1, ?COUNT) ), ok = wait_pids(Pids), #{ <<"docs_count">> :=?COUNT } = barrel_httpc:database_infos(?DB_URL), ok. multiple_get(Config) -> Self = self(), Pids = lists:foldl( fun(I, Acc) -> DocId = << "doc", (integer_to_binary(I))/binary >>, Doc = #{ <<"id">> => DocId, <<"val">> => I}, Pid = spawn_link( fun() -> {ok, DocId, _} = barrel_httpc:post(db(Config), Doc, []), Self ! {ok, self()} end ), [Pid | Acc] end, [], lists:seq(1, ?COUNT) ), ok = wait_pids(Pids), #{ <<"docs_count">> := ?COUNT } = barrel_httpc:database_infos(?DB_URL), Pids1 = lists:foldl( fun(I, Acc) -> DocId = << "doc", (integer_to_binary(I))/binary >>, Pid = spawn_link( fun() -> {ok, #{ <<"id">> := DocId }, _} = barrel_httpc:get(db(Config), DocId, []), Self ! {ok, self()} end ), [Pid | Acc] end, [], lists:seq(1, ?COUNT) ), ok = wait_pids(Pids1), ok. multiple_delete(Config) -> Self = self(), Pids = lists:foldl( fun(I, Acc) -> DocId = << "doc", (integer_to_binary(I))/binary >>, Doc = #{ <<"id">> => DocId, <<"val">> => I}, Pid = spawn_link( fun() -> {ok, DocId, _} = barrel_httpc:post(db(Config), Doc, []), Self ! {ok, self()} end ), [Pid | Acc] end, [], lists:seq(1, ?COUNT) ), wait_pids(Pids), #{ <<"docs_count">> := ?COUNT } = barrel_httpc:database_infos(?DB_URL), Pids1 = lists:foldl( fun(I, Acc) -> DocId = << "doc", (integer_to_binary(I))/binary >>, Pid = spawn_link( fun() -> {ok, #{ <<"id">> := DocId}, #{<<"rev">> := Rev }} = barrel_httpc:get(db(Config), DocId, []), {ok, _, _} = barrel_httpc:delete(db(Config), DocId, [{rev, Rev}]), Self ! {ok, self()} end ), [Pid | Acc] end, [], lists:seq(1, ?COUNT) ), wait_pids(Pids1), #{ <<"docs_count">> := 0 } = barrel_httpc:database_infos(?DB_URL), ok. change_since(Config) -> Fun = fun(Change, Acc) -> Id = maps:get(<<"id">>, Change), {ok, [Id|Acc]} end, {ok, []} = barrel_httpc:changes_since(db(Config), 0, Fun, [], []), Doc = #{ <<"id">> => <<"aa">>, <<"v">> => 1}, {ok, <<"aa">>, _RevId} = barrel_httpc:post(db(Config), Doc, []), {ok, [<<"aa">>]} = barrel_httpc:changes_since(db(Config), 0, Fun, [], []), Doc2 = #{ <<"id">> => <<"bb">>, <<"v">> => 1}, {ok, <<"bb">>, _RevId2} = barrel_httpc:post(db(Config), Doc2, []), {ok, _, _} = barrel_httpc:get(db(Config), <<"bb">>, []), {ok, [<<"bb">>, <<"aa">>]} = barrel_httpc:changes_since(db(Config), 0, Fun, [], []), {ok, [<<"bb">>]} = barrel_httpc:changes_since(db(Config), 1, Fun, [], []), {ok, []} = barrel_httpc:changes_since(db(Config), 2, Fun, [], []), Doc3 = #{ <<"id">> => <<"cc">>, <<"v">> => 1}, {ok, <<"cc">>, _RevId3} = barrel_httpc:post(db(Config), Doc3, []), {ok, [<<"cc">>]} = barrel_httpc:changes_since(db(Config), 2, Fun, [], []), ok. change_deleted(Config) -> Fun = fun(Change, Acc) -> Id = maps:get(<<"id">>, Change), Del = maps:get(<<"deleted">>, Change, false), {ok, [{Id, Del}|Acc]} end, {ok, []} = barrel_httpc:changes_since(db(Config), 0, Fun, [], []), Doc = #{ <<"id">> => <<"aa">>, <<"v">> => 1}, {ok, <<"aa">>, _RevId} = barrel_httpc:post(db(Config), Doc, []), {ok, [{<<"aa">>, false}]} = barrel_httpc:changes_since(db(Config), 0, Fun, [], []), Doc2 = #{ <<"id">> => <<"bb">>, <<"v">> => 1}, {ok, <<"bb">>, RevId2} = barrel_httpc:post(db(Config), Doc2, []), {ok, _, _} = barrel_httpc:get(db(Config), <<"bb">>, []), {ok, [{<<"bb">>, false}, {<<"aa">>, false}]} = barrel_httpc:changes_since(db(Config), 0, Fun, [], []), {ok, [{<<"bb">>, false}]} = barrel_httpc:changes_since(db(Config), 1, Fun, [], []), {ok, <<"bb">>, _} = barrel_httpc:delete(db(Config), <<"bb">>, [{rev, RevId2}]), {ok, [{<<"bb">>, true}]} = barrel_httpc:changes_since(db(Config), 2, Fun, [], []), {ok, [{<<"bb">>, true}, {<<"aa">>, false}]} = barrel_httpc:changes_since(db(Config), 0, Fun, [], []), ok. change_since_include_doc(Config) -> Fun = fun(Change, Acc) -> Seq = maps:get(<<"seq">>, Change), {ok, [{Seq, maps:get(<<"doc">>, Change)} |Acc]} end, Doc = #{ <<"id">> => <<"aa">>, <<"v">> => 1}, {ok, <<"aa">>, _RevId} = barrel_httpc:post(db(Config), Doc, []), {ok, Doc1, _Meta} = barrel_httpc:get(db(Config), <<"aa">>, []), {ok, [Change]} = barrel_httpc:changes_since(db(Config), 0, Fun, [], [{<<"include_doc">>, <<"true">>}]), {1, Doc1} = Change, ok. change_since_many(Config) -> Fun = fun(Change, Acc) -> Seq = maps:get(<<"seq">>, Change), {ok, [{Seq, Change}|Acc]} end, %% No changes. Database is empty. {ok, []} = barrel_httpc:changes_since(db(Config), 0, Fun, [], []), %% Add 20 docs (doc1 to doc20). AddDoc = fun(N) -> K = integer_to_binary(N), Key = <<"doc", K/binary>>, Doc = #{ <<"id">> => Key, <<"v">> => 1}, {ok, Key, _RevId} = barrel_httpc:post(db(Config), Doc, []) end, [AddDoc(N) || N <- lists:seq(1,20)], %% Delete doc1 {ok, _Doc1, #{<<"rev">> := RevId}} = barrel_httpc:get(db(Config), <<"doc1">>, []), {ok, <<"doc1">>, _} = barrel_httpc:delete(db(Config), <<"doc1">>, [{rev, RevId}]), %% 20 changes (for doc1 to doc20) {ok, All} = barrel_httpc:changes_since(db(Config), 0, Fun, [], [{history, all}]), 20 = length(All), %% History for doc1 includes creation and deletion {21, #{<<"changes">> := HistoryDoc1}} = hd(All), 2 = length(HistoryDoc1), {ok, [{21, #{<<"id">> := <<"doc1">>}}, {20, #{<<"id">> := <<"doc20">>}}, {19, #{<<"id">> := <<"doc19">>}}]} = barrel_httpc:changes_since(db(Config), 18, Fun, [], []), {ok, [{21, #{<<"id">> := <<"doc1">>}}, {20, #{<<"id">> := <<"doc20">>}}]} = barrel_httpc:changes_since(db(Config), 19, Fun, [], []), {ok, []} = barrel_httpc:changes_since(db(Config), 21, Fun, [], []), ok. system_docs(_Config) -> Doc = #{<<"v">> => 1}, ok = barrel_httpc:put_system_doc(<<"testdb">>, <<"a">>, Doc), {ok, Doc} = barrel_db:get_system_doc(<<"testdb">>, <<"a">>), ok = barrel_db:delete_system_doc(<<"testdb">>, <<"a">>), {error, not_found} = barrel_db:get_system_doc(<<"testdb">>, <<"a">>), ok. %% internal wait_pids([]) -> ok; wait_pids([Pid|Pids]) -> receive {ok, Pid} -> wait_pids(Pids) after 10000 -> {error, receive_pids} end. %% from barrel_doc in barrel_commons parse_revision(<<"">>) -> {0, <<"">>}; parse_revision(Rev) when is_binary(Rev) -> case binary:split(Rev, <<"-">>) of [BinPos, Hash] -> {binary_to_integer(BinPos), Hash}; _ -> error(bad_rev) end; parse_revision(Rev) when is_list(Rev) -> parse_revision(list_to_binary(Rev)); parse_revision(Rev) -> error({bad_rev, Rev}). parse_revisions(#{ <<"_revisions">> := Revisions}) -> case Revisions of #{ <<"start">> := Start, <<"ids">> := Ids} -> {Revs, _} = lists:foldl( fun(Id, {Acc, I}) -> Acc2 = [<< (integer_to_binary(I))/binary,"-", Id/binary >> | Acc], {Acc2, I - 1} end, {[], Start}, Ids), lists:reverse(Revs); _ -> [] end; parse_revisions(#{<<"_rev">> := Rev}) -> [Rev]; parse_revisions(_) -> []. revid(Pos, Parent, Body0) -> Ctx0 = crypto:hash_init(md5), Body = maps:filter(fun (<<"">>, _) -> false; (<<"_deleted">> , _) -> true; (<<"_", _/binary>>, _) -> false; (_, _) -> true end, Body0), BinPos = integer_to_binary(Pos), Ctx2 = lists:foldl(fun(V, C) -> crypto:hash_update(C, V) end, Ctx0, [BinPos, Parent, term_to_binary(Body)]), Digest = crypto:hash_final(Ctx2), << BinPos/binary, "-", (barrel_httpc_lib:to_hex(Digest))/binary >>. ================================================ FILE: apps/barrel_rest/.gitignore ================================================ .rebar3 _* .eunit *.o *.beam *.plt *.swp *.swo .erlang.cookie ebin log erl_crash.dump .rebar logs _build .idea rebar3.crashdump ================================================ FILE: apps/barrel_rest/LICENSE ================================================ Copyright (c) 2017, Benoit Chesneau . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: apps/barrel_rest/README.md ================================================ barrel_rest ===== An OTP application Build ----- $ rebar3 compile ================================================ FILE: apps/barrel_rest/priv/swagger/css/print.css ================================================ .swagger-section pre code{display:block;padding:.5em;background:#f0f0f0}.swagger-section pre .clojure .built_in,.swagger-section pre .lisp .title,.swagger-section pre .nginx .title,.swagger-section pre .subst,.swagger-section pre .tag .title,.swagger-section pre code{color:#000}.swagger-section pre .addition,.swagger-section pre .aggregate,.swagger-section pre .apache .cbracket,.swagger-section pre .apache .tag,.swagger-section pre .bash .variable,.swagger-section pre .constant,.swagger-section pre .django .variable,.swagger-section pre .erlang_repl .function_or_atom,.swagger-section pre .flow,.swagger-section pre .markdown .header,.swagger-section pre .parent,.swagger-section pre .preprocessor,.swagger-section pre .ruby .symbol,.swagger-section pre .ruby .symbol .string,.swagger-section pre .rules .value,.swagger-section pre .rules .value .number,.swagger-section pre .smalltalk .class,.swagger-section pre .stream,.swagger-section pre .string,.swagger-section pre .tag .value,.swagger-section pre .template_tag,.swagger-section pre .tex .command,.swagger-section pre .tex .special,.swagger-section pre .title{color:#800}.swagger-section pre .annotation,.swagger-section pre .chunk,.swagger-section pre .comment,.swagger-section pre .diff .header,.swagger-section pre .markdown .blockquote,.swagger-section pre .template_comment{color:#888}.swagger-section pre .change,.swagger-section pre .date,.swagger-section pre .go .constant,.swagger-section pre .literal,.swagger-section pre .markdown .bullet,.swagger-section pre .markdown .link_url,.swagger-section pre .number,.swagger-section pre .regexp,.swagger-section pre .smalltalk .char,.swagger-section pre .smalltalk .symbol{color:#080}.swagger-section pre .apache .sqbracket,.swagger-section pre .array,.swagger-section pre .attr_selector,.swagger-section pre .clojure .attribute,.swagger-section pre .coffeescript .property,.swagger-section pre .decorator,.swagger-section pre .deletion,.swagger-section pre .doctype,.swagger-section pre .envvar,.swagger-section pre .erlang_repl .reserved,.swagger-section pre .filter .argument,.swagger-section pre .important,.swagger-section pre .javadoc,.swagger-section pre .label,.swagger-section pre .localvars,.swagger-section pre .markdown .link_label,.swagger-section pre .nginx .built_in,.swagger-section pre .pi,.swagger-section pre .prompt,.swagger-section pre .pseudo,.swagger-section pre .ruby .string,.swagger-section pre .shebang,.swagger-section pre .tex .formula,.swagger-section pre .vhdl .attribute{color:#88f}.swagger-section pre .aggregate,.swagger-section pre .apache .tag,.swagger-section pre .bash .variable,.swagger-section pre .built_in,.swagger-section pre .css .tag,.swagger-section pre .go .typename,.swagger-section pre .id,.swagger-section pre .javadoctag,.swagger-section pre .keyword,.swagger-section pre .markdown .strong,.swagger-section pre .phpdoc,.swagger-section pre .request,.swagger-section pre .smalltalk .class,.swagger-section pre .status,.swagger-section pre .tex .command,.swagger-section pre .title,.swagger-section pre .winutils,.swagger-section pre .yardoctag{font-weight:700}.swagger-section pre .markdown .emphasis{font-style:italic}.swagger-section pre .nginx .built_in{font-weight:400}.swagger-section pre .coffeescript .javascript,.swagger-section pre .javascript .xml,.swagger-section pre .tex .formula,.swagger-section pre .xml .cdata,.swagger-section pre .xml .css,.swagger-section pre .xml .javascript,.swagger-section pre .xml .vbscript{opacity:.5}.swagger-section .hljs{display:block;overflow-x:auto;padding:.5em;background:#f0f0f0}.swagger-section .hljs,.swagger-section .hljs-subst{color:#444}.swagger-section .hljs-attribute,.swagger-section .hljs-doctag,.swagger-section .hljs-keyword,.swagger-section .hljs-meta-keyword,.swagger-section .hljs-name,.swagger-section .hljs-selector-tag{font-weight:700}.swagger-section .hljs-addition,.swagger-section .hljs-built_in,.swagger-section .hljs-bullet,.swagger-section .hljs-code,.swagger-section .hljs-literal{color:#1f811f}.swagger-section .hljs-link,.swagger-section .hljs-regexp,.swagger-section .hljs-selector-attr,.swagger-section .hljs-selector-pseudo,.swagger-section .hljs-symbol,.swagger-section .hljs-template-variable,.swagger-section .hljs-variable{color:#bc6060}.swagger-section .hljs-deletion,.swagger-section .hljs-number,.swagger-section .hljs-quote,.swagger-section .hljs-selector-class,.swagger-section .hljs-selector-id,.swagger-section .hljs-string,.swagger-section .hljs-template-tag,.swagger-section .hljs-type{color:#800}.swagger-section .hljs-section,.swagger-section .hljs-title{color:#800;font-weight:700}.swagger-section .hljs-comment{color:#888}.swagger-section .hljs-meta{color:#2b6ea1}.swagger-section .hljs-emphasis{font-style:italic}.swagger-section .hljs-strong{font-weight:700}.swagger-section .swagger-ui-wrap{line-height:1;font-family:Droid Sans,sans-serif;min-width:760px;max-width:960px;margin-left:auto;margin-right:auto}.swagger-section .swagger-ui-wrap b,.swagger-section .swagger-ui-wrap strong{font-family:Droid Sans,sans-serif;font-weight:700}.swagger-section .swagger-ui-wrap blockquote,.swagger-section .swagger-ui-wrap q{quotes:none}.swagger-section .swagger-ui-wrap p{line-height:1.4em;padding:0 0 10px;color:#333}.swagger-section .swagger-ui-wrap blockquote:after,.swagger-section .swagger-ui-wrap blockquote:before,.swagger-section .swagger-ui-wrap q:after,.swagger-section .swagger-ui-wrap q:before{content:none}.swagger-section .swagger-ui-wrap .heading_with_menu h1,.swagger-section .swagger-ui-wrap .heading_with_menu h2,.swagger-section .swagger-ui-wrap .heading_with_menu h3,.swagger-section .swagger-ui-wrap .heading_with_menu h4,.swagger-section .swagger-ui-wrap .heading_with_menu h5,.swagger-section .swagger-ui-wrap .heading_with_menu h6{display:block;clear:none;float:left;-ms-box-sizing:border-box;box-sizing:border-box;width:60%}.swagger-section .swagger-ui-wrap table{border-collapse:collapse;border-spacing:0}.swagger-section .swagger-ui-wrap table thead tr th{padding:5px;font-size:.9em;color:#666;border-bottom:1px solid #999}.swagger-section .swagger-ui-wrap table tbody tr:last-child td{border-bottom:none}.swagger-section .swagger-ui-wrap table tbody tr.offset{background-color:#f0f0f0}.swagger-section .swagger-ui-wrap table tbody tr td{padding:6px;font-size:.9em;border-bottom:1px solid #ccc;vertical-align:top;line-height:1.3em}.swagger-section .swagger-ui-wrap ol{margin:0 0 10px;padding:0 0 0 18px;list-style-type:decimal}.swagger-section .swagger-ui-wrap ol li{padding:5px 0;font-size:.9em;color:#333}.swagger-section .swagger-ui-wrap ol,.swagger-section .swagger-ui-wrap ul{list-style:none}.swagger-section .swagger-ui-wrap h1 a,.swagger-section .swagger-ui-wrap h2 a,.swagger-section .swagger-ui-wrap h3 a,.swagger-section .swagger-ui-wrap h4 a,.swagger-section .swagger-ui-wrap h5 a,.swagger-section .swagger-ui-wrap h6 a{text-decoration:none}.swagger-section .swagger-ui-wrap h1 a:hover,.swagger-section .swagger-ui-wrap h2 a:hover,.swagger-section .swagger-ui-wrap h3 a:hover,.swagger-section .swagger-ui-wrap h4 a:hover,.swagger-section .swagger-ui-wrap h5 a:hover,.swagger-section .swagger-ui-wrap h6 a:hover{text-decoration:underline}.swagger-section .swagger-ui-wrap h1 span.divider,.swagger-section .swagger-ui-wrap h2 span.divider,.swagger-section .swagger-ui-wrap h3 span.divider,.swagger-section .swagger-ui-wrap h4 span.divider,.swagger-section .swagger-ui-wrap h5 span.divider,.swagger-section .swagger-ui-wrap h6 span.divider{color:#aaa}.swagger-section .swagger-ui-wrap a{color:#547f00}.swagger-section .swagger-ui-wrap a img{border:none}.swagger-section .swagger-ui-wrap article,.swagger-section .swagger-ui-wrap aside,.swagger-section .swagger-ui-wrap details,.swagger-section .swagger-ui-wrap figcaption,.swagger-section .swagger-ui-wrap figure,.swagger-section .swagger-ui-wrap footer,.swagger-section .swagger-ui-wrap header,.swagger-section .swagger-ui-wrap hgroup,.swagger-section .swagger-ui-wrap menu,.swagger-section .swagger-ui-wrap nav,.swagger-section .swagger-ui-wrap section,.swagger-section .swagger-ui-wrap summary{display:block}.swagger-section .swagger-ui-wrap pre{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace;background-color:#fcf6db;border:1px solid #e5e0c6;padding:10px}.swagger-section .swagger-ui-wrap pre code{line-height:1.6em;background:none}.swagger-section .swagger-ui-wrap .content>.content-type>div>label{clear:both;display:block;color:#0f6ab4;font-size:1.1em;margin:0;padding:15px 0 5px}.swagger-section .swagger-ui-wrap .content pre{font-size:12px;margin-top:5px;padding:5px}.swagger-section .swagger-ui-wrap .icon-btn{cursor:pointer}.swagger-section .swagger-ui-wrap .info_title{padding-bottom:10px;font-weight:700;font-size:25px}.swagger-section .swagger-ui-wrap .footer{margin-top:20px}.swagger-section .swagger-ui-wrap div.big p,.swagger-section .swagger-ui-wrap p.big{font-size:1em;margin-bottom:10px}.swagger-section .swagger-ui-wrap form.fullwidth ol li.numeric input,.swagger-section .swagger-ui-wrap form.fullwidth ol li.string input,.swagger-section .swagger-ui-wrap form.fullwidth ol li.text textarea,.swagger-section .swagger-ui-wrap form.fullwidth ol li.url input{width:500px!important}.swagger-section .swagger-ui-wrap .info_license,.swagger-section .swagger-ui-wrap .info_tos{padding-bottom:5px}.swagger-section .swagger-ui-wrap .message-fail{color:#c00}.swagger-section .swagger-ui-wrap .info_email,.swagger-section .swagger-ui-wrap .info_name,.swagger-section .swagger-ui-wrap .info_url{padding-bottom:5px}.swagger-section .swagger-ui-wrap .info_description{padding-bottom:10px;font-size:15px}.swagger-section .swagger-ui-wrap .markdown ol li,.swagger-section .swagger-ui-wrap .markdown ul li{padding:3px 0;line-height:1.4em;color:#333}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.numeric input,.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.string input,.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.url input{display:block;padding:4px;width:auto;clear:both}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.numeric input.title,.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.string input.title,.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.url input.title{font-size:1.3em}.swagger-section .swagger-ui-wrap table.fullwidth{width:100%}.swagger-section .swagger-ui-wrap .model-signature{font-family:Droid Sans,sans-serif;font-size:1em;line-height:1.5em}.swagger-section .swagger-ui-wrap .model-signature .signature-nav a{text-decoration:none;color:#aaa}.swagger-section .swagger-ui-wrap .model-signature .signature-nav a:hover{text-decoration:underline;color:#000}.swagger-section .swagger-ui-wrap .model-signature .signature-nav .selected{color:#000;text-decoration:none}.swagger-section .swagger-ui-wrap .model-signature .propType{color:#55a}.swagger-section .swagger-ui-wrap .model-signature pre:hover{background-color:#ffd}.swagger-section .swagger-ui-wrap .model-signature pre{font-size:.85em;line-height:1.2em;overflow:auto;height:200px;resize:vertical;cursor:pointer}.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav{display:block;min-width:230px;margin:0;padding:0}.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav li:last-child{padding-right:0;border-right:none}.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav li{float:left;margin:0 5px 5px 0;padding:2px 5px 2px 0;border-right:1px solid #ddd}.swagger-section .swagger-ui-wrap .model-signature .propOpt{color:#555}.swagger-section .swagger-ui-wrap .model-signature .snippet small{font-size:.75em}.swagger-section .swagger-ui-wrap .model-signature .propOptKey{font-style:italic}.swagger-section .swagger-ui-wrap .model-signature .description .strong{font-weight:700;color:#000;font-size:.9em}.swagger-section .swagger-ui-wrap .model-signature .description div{font-size:.9em;line-height:1.5em;margin-left:1em}.swagger-section .swagger-ui-wrap .model-signature .description .stronger{font-weight:700;color:#000}.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper{border-spacing:0;position:absolute;background-color:#fff;border:1px solid #bbb;display:none;font-size:11px;max-width:400px;line-height:30px;color:#000;padding:5px;margin-left:10px}.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper th{text-align:center;background-color:#eee;border:1px solid #bbb;font-size:11px;color:#666;font-weight:700;padding:5px;line-height:15px}.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper .optionName{font-weight:700}.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown>p:first-child,.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown>p:last-child{display:inline}.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown>p:not(:first-child):before{display:block;content:""}.swagger-section .swagger-ui-wrap .model-signature .description span:last-of-type.propDesc.markdown>p:only-child{margin-right:-3px}.swagger-section .swagger-ui-wrap .model-signature .propName{font-weight:700}.swagger-section .swagger-ui-wrap .model-signature .signature-container{clear:both}.swagger-section .swagger-ui-wrap .body-textarea{width:300px;height:100px;border:1px solid #aaa}.swagger-section .swagger-ui-wrap .markdown li code,.swagger-section .swagger-ui-wrap .markdown p code{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace;background-color:#f0f0f0;color:#000;padding:1px 3px}.swagger-section .swagger-ui-wrap .required{font-weight:700}.swagger-section .swagger-ui-wrap .editor_holder{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace;font-size:.9em}.swagger-section .swagger-ui-wrap .editor_holder label{font-weight:400!important}.swagger-section .swagger-ui-wrap .editor_holder label.required{font-weight:700!important}.swagger-section .swagger-ui-wrap input.parameter{width:300px;border:1px solid #aaa}.swagger-section .swagger-ui-wrap h1{color:#000;font-size:1.5em;line-height:1.3em;padding:10px 0;font-family:Droid Sans,sans-serif;font-weight:700}.swagger-section .swagger-ui-wrap .heading_with_menu{float:none;clear:both;overflow:hidden;display:block}.swagger-section .swagger-ui-wrap .heading_with_menu ul{display:block;clear:none;float:right;-ms-box-sizing:border-box;box-sizing:border-box;margin-top:10px}.swagger-section .swagger-ui-wrap h2{color:#000;font-size:1.3em;padding:10px 0}.swagger-section .swagger-ui-wrap h2 a{color:#000}.swagger-section .swagger-ui-wrap h2 span.sub{font-size:.7em;color:#999;font-style:italic}.swagger-section .swagger-ui-wrap h2 span.sub a{color:#777}.swagger-section .swagger-ui-wrap span.weak{color:#666}.swagger-section .swagger-ui-wrap .message-success{color:#89bf04}.swagger-section .swagger-ui-wrap caption,.swagger-section .swagger-ui-wrap td,.swagger-section .swagger-ui-wrap th{text-align:left;font-weight:400;vertical-align:middle}.swagger-section .swagger-ui-wrap .code{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.text textarea{font-family:Droid Sans,sans-serif;height:250px;padding:4px;display:block;clear:both}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.select select{display:block;clear:both}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean{float:none;clear:both;overflow:hidden;display:block}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean label{display:block;float:left;clear:none;margin:0;padding:0}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean input{display:block;float:left;clear:none;margin:0 5px 0 0}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.required label{color:#000}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li label{display:block;clear:both;width:auto;padding:0 0 3px;color:#666}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li label abbr{padding-left:3px;color:#888}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li p.inline-hints{margin-left:0;font-style:italic;font-size:.9em;margin:0}.swagger-section .swagger-ui-wrap form.formtastic fieldset.buttons{margin:0;padding:0}.swagger-section .swagger-ui-wrap span.blank,.swagger-section .swagger-ui-wrap span.empty{color:#888;font-style:italic}.swagger-section .swagger-ui-wrap .markdown h3{color:#547f00}.swagger-section .swagger-ui-wrap .markdown h4{color:#666}.swagger-section .swagger-ui-wrap .markdown pre{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace;background-color:#fcf6db;border:1px solid #e5e0c6;padding:10px;margin:0 0 10px}.swagger-section .swagger-ui-wrap .markdown pre code{line-height:1.6em;overflow:auto}.swagger-section .swagger-ui-wrap div.gist{margin:20px 0 25px!important}.swagger-section .swagger-ui-wrap ul#resources{font-family:Droid Sans,sans-serif;font-size:.9em}.swagger-section .swagger-ui-wrap ul#resources li.resource{border-bottom:1px solid #ddd}.swagger-section .swagger-ui-wrap ul#resources li.resource.active div.heading h2 a,.swagger-section .swagger-ui-wrap ul#resources li.resource:hover div.heading h2 a{color:#000}.swagger-section .swagger-ui-wrap ul#resources li.resource.active div.heading ul.options li a,.swagger-section .swagger-ui-wrap ul#resources li.resource:hover div.heading ul.options li a{color:#555}.swagger-section .swagger-ui-wrap ul#resources li.resource:last-child{border-bottom:none}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading{border:1px solid transparent;float:none;clear:both;overflow:hidden;display:block}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options{overflow:hidden;padding:0;display:block;clear:none;float:right;margin:14px 10px 0 0}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li{float:left;clear:none;margin:0;padding:2px 10px;border-right:1px solid #ddd;color:#666;font-size:.9em}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a{color:#aaa;text-decoration:none}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:hover{text-decoration:underline;color:#000}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a.active,.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:active,.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:hover{text-decoration:underline}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li.first,.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li:first-child{padding-left:0}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li:last-child{padding-right:0;border-right:none}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options.first,.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options:first-child{padding-left:0}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2{color:#999;padding-left:0;display:block;clear:none;float:left;font-family:Droid Sans,sans-serif;font-weight:700}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a{color:#999}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a:hover{color:#000}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation{float:none;clear:both;overflow:hidden;display:block;margin:0 0 10px;padding:0}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading{float:none;clear:both;overflow:hidden;display:block;margin:0;padding:0}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3{display:block;clear:none;float:left;width:auto;margin:0;padding:0;line-height:1.1em;color:#000}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path{padding-left:10px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path a{color:#000;text-decoration:none}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path a.toggleOperation.deprecated{text-decoration:line-through}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path a:hover{text-decoration:underline}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.http_method a{text-transform:uppercase;text-decoration:none;color:#fff;display:inline-block;width:50px;font-size:.7em;text-align:center;padding:7px 0 4px;border-radius:2px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span{margin:0;padding:0}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options{overflow:hidden;padding:0;display:block;clear:none;float:right;margin:6px 10px 0 0}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li{float:left;clear:none;margin:0;padding:2px 10px;font-size:.9em}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li a{text-decoration:none}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li a .markdown p{color:inherit;padding:0;line-height:inherit}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li a .nickname{color:#aaa;padding:0;line-height:inherit}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li.access{color:#000}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content{border-top:none;padding:10px;border-bottom-left-radius:6px;border-bottom-right-radius:6px;margin:0 0 20px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content h4{font-size:1.1em;margin:0;padding:15px 0 5px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header{float:none;clear:both;overflow:hidden;display:block}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header a{padding:4px 0 0 10px;display:inline-block;font-size:.9em}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header input.submit{display:block;clear:none;float:left;padding:6px 8px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header span.response_throbber{background-image:url(../images/throbber.gif);width:128px;height:16px;display:block;clear:none;float:right}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content form input[type=text].error{outline:2px solid #000;outline-color:#c00}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content form select[name=parameterContentType]{max-width:300px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.response div.block pre{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace;padding:10px;font-size:.9em;max-height:400px;overflow-y:auto}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading{background-color:#f9f2e9;border:1px solid #f0e0ca}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading h3 span.http_method a{background-color:#c5862b}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#f0e0ca;color:#c5862b}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li a{color:#c5862b}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content{background-color:#faf5ee;border:1px solid #f0e0ca}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content h4{color:#c5862b}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content div.sandbox_header a{color:#dcb67f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading{background-color:#fcffcd;border:1px solid #000;border-color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading h3 span.http_method a{text-transform:uppercase;background-color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#ffd20f;color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li a{color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content{background-color:#fcffcd;border:1px solid #000;border-color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content h4{color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content div.sandbox_header a{color:#6fc992}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading{background-color:#f5e8e8;border:1px solid #e8c6c7}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading h3 span.http_method a{text-transform:uppercase;background-color:#a41e22}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#e8c6c7;color:#a41e22}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li a{color:#a41e22}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content{background-color:#f7eded;border:1px solid #e8c6c7}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content h4{color:#a41e22}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content div.sandbox_header a{color:#c8787a}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading{background-color:#e7f6ec;border:1px solid #c3e8d1}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading h3 span.http_method a{background-color:#10a54a}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#c3e8d1;color:#10a54a}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li a{color:#10a54a}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content{background-color:#ebf7f0;border:1px solid #c3e8d1}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content h4{color:#10a54a}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content div.sandbox_header a{color:#6fc992}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading{background-color:#fce9e3;border:1px solid #f5d5c3}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading h3 span.http_method a{background-color:#d38042}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#f0cecb;color:#d38042}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li a{color:#d38042}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content{background-color:#faf0ef;border:1px solid #f0cecb}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content h4{color:#d38042}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content div.sandbox_header a{color:#dcb67f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading{background-color:#e7f0f7;border:1px solid #c3d9ec}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading h3 span.http_method a{background-color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#c3d9ec;color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li a{color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content{background-color:#ebf3f9;border:1px solid #c3d9ec}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content h4{color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content div.sandbox_header a{color:#6fa5d2}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading{background-color:#e7f0f7;border:1px solid #c3d9ec}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading h3 span.http_method a{background-color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#c3d9ec;color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading ul.options li a{color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content{background-color:#ebf3f9;border:1px solid #c3d9ec}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content h4{color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content div.sandbox_header a{color:#6fa5d2}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content{border-top:none}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li:last-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li:last-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li:last-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li:last-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li:last-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li:last-child{padding-right:0;border-right:none}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a.active,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a:active,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a:hover{text-decoration:underline}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations.first,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations:first-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li.first,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li:first-child{padding-left:0}.swagger-section .swagger-ui-wrap p#colophon{margin:0 15px 40px;padding:10px 0;font-size:.8em;border-top:1px solid #ddd;font-family:Droid Sans,sans-serif;color:#999;font-style:italic}.swagger-section .swagger-ui-wrap p#colophon a{text-decoration:none;color:#547f00}.swagger-section .swagger-ui-wrap h3{color:#000;font-size:1.1em;padding:10px 0}.swagger-section .swagger-ui-wrap .markdown ol,.swagger-section .swagger-ui-wrap .markdown ul{font-family:Droid Sans,sans-serif;margin:5px 0 10px;padding:0 0 0 18px;list-style-type:disc}.swagger-section .swagger-ui-wrap form.form_box{background-color:#ebf3f9;border:1px solid #c3d9ec;padding:10px}.swagger-section .swagger-ui-wrap form.form_box label{color:#0f6ab4!important}.swagger-section .swagger-ui-wrap form.form_box input[type=submit]{display:block;padding:10px}.swagger-section .swagger-ui-wrap form.form_box p.weak{font-size:.8em}.swagger-section .swagger-ui-wrap form.form_box p{font-size:.9em;padding:0 0 15px;color:#7e7b6d}.swagger-section .swagger-ui-wrap form.form_box p a{color:#646257}.swagger-section .swagger-ui-wrap form.form_box p strong{color:#000}.swagger-section .swagger-ui-wrap .operation-status td.markdown>p:last-child{padding-bottom:0}.swagger-section .title{font-style:bold}.swagger-section .secondary_form{display:none}.swagger-section .main_image{display:block;margin-left:auto;margin-right:auto}.swagger-section .oauth_body{margin-left:100px;margin-right:100px}.swagger-section .oauth_submit{text-align:center;display:inline-block}.swagger-section .authorize-wrapper{margin:15px 0 10px}.swagger-section .authorize-wrapper_operation{float:right}.swagger-section .authorize__btn:hover{text-decoration:underline;cursor:pointer}.swagger-section .authorize__btn_operation:hover .authorize-scopes{display:block}.swagger-section .authorize-scopes{position:absolute;margin-top:20px;background:#fff;border:1px solid #ccc;border-radius:5px;display:none;font-size:13px;max-width:300px;line-height:30px;color:#000;padding:5px}.swagger-section .authorize-scopes .authorize__scope{text-decoration:none}.swagger-section .authorize__btn_operation{height:18px;vertical-align:middle;display:inline-block;background:url(../images/explorer_icons.png) no-repeat}.swagger-section .authorize__btn_operation_login{background-position:0 0;width:18px;margin-top:-6px;margin-left:4px}.swagger-section .authorize__btn_operation_logout{background-position:-30px 0;width:18px;margin-top:-6px;margin-left:4px}.swagger-section #auth_container{color:#fff;display:inline-block;border:none;padding:5px;width:87px;height:13px}.swagger-section #auth_container .authorize__btn{color:#fff}.swagger-section .auth_container{padding:0 0 10px;margin-bottom:5px;border-bottom:1px solid #ccc;font-size:.9em}.swagger-section .auth_container .auth__title{color:#547f00;font-size:1.2em}.swagger-section .auth_container .basic_auth__label{display:inline-block;width:60px}.swagger-section .auth_container .auth__description{color:#999;margin-bottom:5px}.swagger-section .auth_container .auth__button{margin-top:10px;height:30px}.swagger-section .auth_container .key_auth__field{margin:5px 0}.swagger-section .auth_container .key_auth__label{display:inline-block;width:60px}.swagger-section .api-popup-dialog{position:absolute;display:none}.swagger-section .api-popup-dialog-wrapper{z-index:2;width:500px;background:#fff;padding:20px;border:1px solid #ccc;border-radius:5px;font-size:13px;color:#777;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%)}.swagger-section .api-popup-dialog-shadow{position:fixed;top:0;left:0;width:100%;height:100%;opacity:.2;background-color:gray;z-index:1}.swagger-section .api-popup-dialog .api-popup-title{font-size:24px;padding:10px 0}.swagger-section .api-popup-dialog .error-msg{padding-left:5px;padding-bottom:5px}.swagger-section .api-popup-dialog .api-popup-content{max-height:500px;overflow-y:auto}.swagger-section .api-popup-dialog .api-popup-authbtn,.swagger-section .api-popup-dialog .api-popup-cancel{height:30px}.swagger-section .api-popup-scopes{padding:10px 20px}.swagger-section .api-popup-scopes li{padding:5px 0;line-height:20px}.swagger-section .api-popup-scopes li input{position:relative;top:2px}.swagger-section .api-popup-scopes .api-scope-desc{padding-left:20px;font-style:italic}.swagger-section .api-popup-actions{padding-top:10px}.swagger-section fieldset{padding-bottom:10px;padding-left:20px}#header{display:none}.swagger-section .swagger-ui-wrap .model-signature pre{max-height:none}.swagger-section .swagger-ui-wrap .body-textarea,.swagger-section .swagger-ui-wrap input.parameter{width:100px}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options{display:none}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content{display:block!important} ================================================ FILE: apps/barrel_rest/priv/swagger/css/reset.css ================================================ a,abbr,acronym,address,applet,article,aside,audio,b,big,blockquote,body,canvas,caption,center,cite,code,dd,del,details,dfn,div,dl,dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,output,p,pre,q,ruby,s,samp,section,small,span,strike,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,tt,u,ul,var,video{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:after,blockquote:before,q:after,q:before{content:"";content:none}table{border-collapse:collapse;border-spacing:0} ================================================ FILE: apps/barrel_rest/priv/swagger/css/screen.css ================================================ .swagger-section pre code{display:block;padding:.5em;background:#f0f0f0}.swagger-section pre .clojure .built_in,.swagger-section pre .lisp .title,.swagger-section pre .nginx .title,.swagger-section pre .subst,.swagger-section pre .tag .title,.swagger-section pre code{color:#000}.swagger-section pre .addition,.swagger-section pre .aggregate,.swagger-section pre .apache .cbracket,.swagger-section pre .apache .tag,.swagger-section pre .bash .variable,.swagger-section pre .constant,.swagger-section pre .django .variable,.swagger-section pre .erlang_repl .function_or_atom,.swagger-section pre .flow,.swagger-section pre .markdown .header,.swagger-section pre .parent,.swagger-section pre .preprocessor,.swagger-section pre .ruby .symbol,.swagger-section pre .ruby .symbol .string,.swagger-section pre .rules .value,.swagger-section pre .rules .value .number,.swagger-section pre .smalltalk .class,.swagger-section pre .stream,.swagger-section pre .string,.swagger-section pre .tag .value,.swagger-section pre .template_tag,.swagger-section pre .tex .command,.swagger-section pre .tex .special,.swagger-section pre .title{color:#800}.swagger-section pre .annotation,.swagger-section pre .chunk,.swagger-section pre .comment,.swagger-section pre .diff .header,.swagger-section pre .markdown .blockquote,.swagger-section pre .template_comment{color:#888}.swagger-section pre .change,.swagger-section pre .date,.swagger-section pre .go .constant,.swagger-section pre .literal,.swagger-section pre .markdown .bullet,.swagger-section pre .markdown .link_url,.swagger-section pre .number,.swagger-section pre .regexp,.swagger-section pre .smalltalk .char,.swagger-section pre .smalltalk .symbol{color:#080}.swagger-section pre .apache .sqbracket,.swagger-section pre .array,.swagger-section pre .attr_selector,.swagger-section pre .clojure .attribute,.swagger-section pre .coffeescript .property,.swagger-section pre .decorator,.swagger-section pre .deletion,.swagger-section pre .doctype,.swagger-section pre .envvar,.swagger-section pre .erlang_repl .reserved,.swagger-section pre .filter .argument,.swagger-section pre .important,.swagger-section pre .javadoc,.swagger-section pre .label,.swagger-section pre .localvars,.swagger-section pre .markdown .link_label,.swagger-section pre .nginx .built_in,.swagger-section pre .pi,.swagger-section pre .prompt,.swagger-section pre .pseudo,.swagger-section pre .ruby .string,.swagger-section pre .shebang,.swagger-section pre .tex .formula,.swagger-section pre .vhdl .attribute{color:#88f}.swagger-section pre .aggregate,.swagger-section pre .apache .tag,.swagger-section pre .bash .variable,.swagger-section pre .built_in,.swagger-section pre .css .tag,.swagger-section pre .go .typename,.swagger-section pre .id,.swagger-section pre .javadoctag,.swagger-section pre .keyword,.swagger-section pre .markdown .strong,.swagger-section pre .phpdoc,.swagger-section pre .request,.swagger-section pre .smalltalk .class,.swagger-section pre .status,.swagger-section pre .tex .command,.swagger-section pre .title,.swagger-section pre .winutils,.swagger-section pre .yardoctag{font-weight:700}.swagger-section pre .markdown .emphasis{font-style:italic}.swagger-section pre .nginx .built_in{font-weight:400}.swagger-section pre .coffeescript .javascript,.swagger-section pre .javascript .xml,.swagger-section pre .tex .formula,.swagger-section pre .xml .cdata,.swagger-section pre .xml .css,.swagger-section pre .xml .javascript,.swagger-section pre .xml .vbscript{opacity:.5}.swagger-section .hljs{display:block;overflow-x:auto;padding:.5em;background:#f0f0f0}.swagger-section .hljs,.swagger-section .hljs-subst{color:#444}.swagger-section .hljs-attribute,.swagger-section .hljs-doctag,.swagger-section .hljs-keyword,.swagger-section .hljs-meta-keyword,.swagger-section .hljs-name,.swagger-section .hljs-selector-tag{font-weight:700}.swagger-section .hljs-addition,.swagger-section .hljs-built_in,.swagger-section .hljs-bullet,.swagger-section .hljs-code,.swagger-section .hljs-literal{color:#1f811f}.swagger-section .hljs-link,.swagger-section .hljs-regexp,.swagger-section .hljs-selector-attr,.swagger-section .hljs-selector-pseudo,.swagger-section .hljs-symbol,.swagger-section .hljs-template-variable,.swagger-section .hljs-variable{color:#bc6060}.swagger-section .hljs-deletion,.swagger-section .hljs-number,.swagger-section .hljs-quote,.swagger-section .hljs-selector-class,.swagger-section .hljs-selector-id,.swagger-section .hljs-string,.swagger-section .hljs-template-tag,.swagger-section .hljs-type{color:#800}.swagger-section .hljs-section,.swagger-section .hljs-title{color:#800;font-weight:700}.swagger-section .hljs-comment{color:#888}.swagger-section .hljs-meta{color:#2b6ea1}.swagger-section .hljs-emphasis{font-style:italic}.swagger-section .hljs-strong{font-weight:700}.swagger-section .swagger-ui-wrap{line-height:1;font-family:Droid Sans,sans-serif;min-width:760px;max-width:960px;margin-left:auto;margin-right:auto}.swagger-section .swagger-ui-wrap b,.swagger-section .swagger-ui-wrap strong{font-family:Droid Sans,sans-serif;font-weight:700}.swagger-section .swagger-ui-wrap blockquote,.swagger-section .swagger-ui-wrap q{quotes:none}.swagger-section .swagger-ui-wrap p{line-height:1.4em;padding:0 0 10px;color:#333}.swagger-section .swagger-ui-wrap blockquote:after,.swagger-section .swagger-ui-wrap blockquote:before,.swagger-section .swagger-ui-wrap q:after,.swagger-section .swagger-ui-wrap q:before{content:none}.swagger-section .swagger-ui-wrap .heading_with_menu h1,.swagger-section .swagger-ui-wrap .heading_with_menu h2,.swagger-section .swagger-ui-wrap .heading_with_menu h3,.swagger-section .swagger-ui-wrap .heading_with_menu h4,.swagger-section .swagger-ui-wrap .heading_with_menu h5,.swagger-section .swagger-ui-wrap .heading_with_menu h6{display:block;clear:none;float:left;-ms-box-sizing:border-box;box-sizing:border-box;width:60%}.swagger-section .swagger-ui-wrap table{border-collapse:collapse;border-spacing:0}.swagger-section .swagger-ui-wrap table thead tr th{padding:5px;font-size:.9em;color:#666;border-bottom:1px solid #999}.swagger-section .swagger-ui-wrap table tbody tr:last-child td{border-bottom:none}.swagger-section .swagger-ui-wrap table tbody tr.offset{background-color:#f0f0f0}.swagger-section .swagger-ui-wrap table tbody tr td{padding:6px;font-size:.9em;border-bottom:1px solid #ccc;vertical-align:top;line-height:1.3em}.swagger-section .swagger-ui-wrap ol{margin:0 0 10px;padding:0 0 0 18px;list-style-type:decimal}.swagger-section .swagger-ui-wrap ol li{padding:5px 0;font-size:.9em;color:#333}.swagger-section .swagger-ui-wrap ol,.swagger-section .swagger-ui-wrap ul{list-style:none}.swagger-section .swagger-ui-wrap h1 a,.swagger-section .swagger-ui-wrap h2 a,.swagger-section .swagger-ui-wrap h3 a,.swagger-section .swagger-ui-wrap h4 a,.swagger-section .swagger-ui-wrap h5 a,.swagger-section .swagger-ui-wrap h6 a{text-decoration:none}.swagger-section .swagger-ui-wrap h1 a:hover,.swagger-section .swagger-ui-wrap h2 a:hover,.swagger-section .swagger-ui-wrap h3 a:hover,.swagger-section .swagger-ui-wrap h4 a:hover,.swagger-section .swagger-ui-wrap h5 a:hover,.swagger-section .swagger-ui-wrap h6 a:hover{text-decoration:underline}.swagger-section .swagger-ui-wrap h1 span.divider,.swagger-section .swagger-ui-wrap h2 span.divider,.swagger-section .swagger-ui-wrap h3 span.divider,.swagger-section .swagger-ui-wrap h4 span.divider,.swagger-section .swagger-ui-wrap h5 span.divider,.swagger-section .swagger-ui-wrap h6 span.divider{color:#aaa}.swagger-section .swagger-ui-wrap a{color:#547f00}.swagger-section .swagger-ui-wrap a img{border:none}.swagger-section .swagger-ui-wrap article,.swagger-section .swagger-ui-wrap aside,.swagger-section .swagger-ui-wrap details,.swagger-section .swagger-ui-wrap figcaption,.swagger-section .swagger-ui-wrap figure,.swagger-section .swagger-ui-wrap footer,.swagger-section .swagger-ui-wrap header,.swagger-section .swagger-ui-wrap hgroup,.swagger-section .swagger-ui-wrap menu,.swagger-section .swagger-ui-wrap nav,.swagger-section .swagger-ui-wrap section,.swagger-section .swagger-ui-wrap summary{display:block}.swagger-section .swagger-ui-wrap pre{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace;background-color:#fcf6db;border:1px solid #e5e0c6;padding:10px}.swagger-section .swagger-ui-wrap pre code{line-height:1.6em;background:none}.swagger-section .swagger-ui-wrap .content>.content-type>div>label{clear:both;display:block;color:#0f6ab4;font-size:1.1em;margin:0;padding:15px 0 5px}.swagger-section .swagger-ui-wrap .content pre{font-size:12px;margin-top:5px;padding:5px}.swagger-section .swagger-ui-wrap .icon-btn{cursor:pointer}.swagger-section .swagger-ui-wrap .info_title{padding-bottom:10px;font-weight:700;font-size:25px}.swagger-section .swagger-ui-wrap .footer{margin-top:20px}.swagger-section .swagger-ui-wrap div.big p,.swagger-section .swagger-ui-wrap p.big{font-size:1em;margin-bottom:10px}.swagger-section .swagger-ui-wrap form.fullwidth ol li.numeric input,.swagger-section .swagger-ui-wrap form.fullwidth ol li.string input,.swagger-section .swagger-ui-wrap form.fullwidth ol li.text textarea,.swagger-section .swagger-ui-wrap form.fullwidth ol li.url input{width:500px!important}.swagger-section .swagger-ui-wrap .info_license,.swagger-section .swagger-ui-wrap .info_tos{padding-bottom:5px}.swagger-section .swagger-ui-wrap .message-fail{color:#c00}.swagger-section .swagger-ui-wrap .info_email,.swagger-section .swagger-ui-wrap .info_name,.swagger-section .swagger-ui-wrap .info_url{padding-bottom:5px}.swagger-section .swagger-ui-wrap .info_description{padding-bottom:10px;font-size:15px}.swagger-section .swagger-ui-wrap .markdown ol li,.swagger-section .swagger-ui-wrap .markdown ul li{padding:3px 0;line-height:1.4em;color:#333}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.numeric input,.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.string input,.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.url input{display:block;padding:4px;width:auto;clear:both}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.numeric input.title,.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.string input.title,.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.url input.title{font-size:1.3em}.swagger-section .swagger-ui-wrap table.fullwidth{width:100%}.swagger-section .swagger-ui-wrap .model-signature{font-family:Droid Sans,sans-serif;font-size:1em;line-height:1.5em}.swagger-section .swagger-ui-wrap .model-signature .signature-nav a{text-decoration:none;color:#aaa}.swagger-section .swagger-ui-wrap .model-signature .signature-nav a:hover{text-decoration:underline;color:#000}.swagger-section .swagger-ui-wrap .model-signature .signature-nav .selected{color:#000;text-decoration:none}.swagger-section .swagger-ui-wrap .model-signature .propType{color:#55a}.swagger-section .swagger-ui-wrap .model-signature pre:hover{background-color:#ffd}.swagger-section .swagger-ui-wrap .model-signature pre{font-size:.85em;line-height:1.2em;overflow:auto;height:200px;resize:vertical;cursor:pointer}.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav{display:block;min-width:230px;margin:0;padding:0}.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav li:last-child{padding-right:0;border-right:none}.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav li{float:left;margin:0 5px 5px 0;padding:2px 5px 2px 0;border-right:1px solid #ddd}.swagger-section .swagger-ui-wrap .model-signature .propOpt{color:#555}.swagger-section .swagger-ui-wrap .model-signature .snippet small{font-size:.75em}.swagger-section .swagger-ui-wrap .model-signature .propOptKey{font-style:italic}.swagger-section .swagger-ui-wrap .model-signature .description .strong{font-weight:700;color:#000;font-size:.9em}.swagger-section .swagger-ui-wrap .model-signature .description div{font-size:.9em;line-height:1.5em;margin-left:1em}.swagger-section .swagger-ui-wrap .model-signature .description .stronger{font-weight:700;color:#000}.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper{border-spacing:0;position:absolute;background-color:#fff;border:1px solid #bbb;display:none;font-size:11px;max-width:400px;line-height:30px;color:#000;padding:5px;margin-left:10px}.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper th{text-align:center;background-color:#eee;border:1px solid #bbb;font-size:11px;color:#666;font-weight:700;padding:5px;line-height:15px}.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper .optionName{font-weight:700}.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown>p:first-child,.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown>p:last-child{display:inline}.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown>p:not(:first-child):before{display:block;content:""}.swagger-section .swagger-ui-wrap .model-signature .description span:last-of-type.propDesc.markdown>p:only-child{margin-right:-3px}.swagger-section .swagger-ui-wrap .model-signature .propName{font-weight:700}.swagger-section .swagger-ui-wrap .model-signature .signature-container{clear:both}.swagger-section .swagger-ui-wrap .body-textarea{width:300px;height:100px;border:1px solid #aaa}.swagger-section .swagger-ui-wrap .markdown li code,.swagger-section .swagger-ui-wrap .markdown p code{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace;background-color:#f0f0f0;color:#000;padding:1px 3px}.swagger-section .swagger-ui-wrap .required{font-weight:700}.swagger-section .swagger-ui-wrap .editor_holder{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace;font-size:.9em}.swagger-section .swagger-ui-wrap .editor_holder label{font-weight:400!important}.swagger-section .swagger-ui-wrap .editor_holder label.required{font-weight:700!important}.swagger-section .swagger-ui-wrap input.parameter{width:300px;border:1px solid #aaa}.swagger-section .swagger-ui-wrap h1{color:#000;font-size:1.5em;line-height:1.3em;padding:10px 0;font-family:Droid Sans,sans-serif;font-weight:700}.swagger-section .swagger-ui-wrap .heading_with_menu{float:none;clear:both;overflow:hidden;display:block}.swagger-section .swagger-ui-wrap .heading_with_menu ul{display:block;clear:none;float:right;-ms-box-sizing:border-box;box-sizing:border-box;margin-top:10px}.swagger-section .swagger-ui-wrap h2{color:#000;font-size:1.3em;padding:10px 0}.swagger-section .swagger-ui-wrap h2 a{color:#000}.swagger-section .swagger-ui-wrap h2 span.sub{font-size:.7em;color:#999;font-style:italic}.swagger-section .swagger-ui-wrap h2 span.sub a{color:#777}.swagger-section .swagger-ui-wrap span.weak{color:#666}.swagger-section .swagger-ui-wrap .message-success{color:#89bf04}.swagger-section .swagger-ui-wrap caption,.swagger-section .swagger-ui-wrap td,.swagger-section .swagger-ui-wrap th{text-align:left;font-weight:400;vertical-align:middle}.swagger-section .swagger-ui-wrap .code{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.text textarea{font-family:Droid Sans,sans-serif;height:250px;padding:4px;display:block;clear:both}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.select select{display:block;clear:both}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean{float:none;clear:both;overflow:hidden;display:block}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean label{display:block;float:left;clear:none;margin:0;padding:0}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean input{display:block;float:left;clear:none;margin:0 5px 0 0}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.required label{color:#000}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li label{display:block;clear:both;width:auto;padding:0 0 3px;color:#666}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li label abbr{padding-left:3px;color:#888}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li p.inline-hints{margin-left:0;font-style:italic;font-size:.9em;margin:0}.swagger-section .swagger-ui-wrap form.formtastic fieldset.buttons{margin:0;padding:0}.swagger-section .swagger-ui-wrap span.blank,.swagger-section .swagger-ui-wrap span.empty{color:#888;font-style:italic}.swagger-section .swagger-ui-wrap .markdown h3{color:#547f00}.swagger-section .swagger-ui-wrap .markdown h4{color:#666}.swagger-section .swagger-ui-wrap .markdown pre{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace;background-color:#fcf6db;border:1px solid #e5e0c6;padding:10px;margin:0 0 10px}.swagger-section .swagger-ui-wrap .markdown pre code{line-height:1.6em;overflow:auto}.swagger-section .swagger-ui-wrap div.gist{margin:20px 0 25px!important}.swagger-section .swagger-ui-wrap ul#resources{font-family:Droid Sans,sans-serif;font-size:.9em}.swagger-section .swagger-ui-wrap ul#resources li.resource{border-bottom:1px solid #ddd}.swagger-section .swagger-ui-wrap ul#resources li.resource.active div.heading h2 a,.swagger-section .swagger-ui-wrap ul#resources li.resource:hover div.heading h2 a{color:#000}.swagger-section .swagger-ui-wrap ul#resources li.resource.active div.heading ul.options li a,.swagger-section .swagger-ui-wrap ul#resources li.resource:hover div.heading ul.options li a{color:#555}.swagger-section .swagger-ui-wrap ul#resources li.resource:last-child{border-bottom:none}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading{border:1px solid transparent;float:none;clear:both;overflow:hidden;display:block}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options{overflow:hidden;padding:0;display:block;clear:none;float:right;margin:14px 10px 0 0}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li{float:left;clear:none;margin:0;padding:2px 10px;border-right:1px solid #ddd;color:#666;font-size:.9em}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a{color:#aaa;text-decoration:none}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:hover{text-decoration:underline;color:#000}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a.active,.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:active,.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:hover{text-decoration:underline}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li.first,.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li:first-child{padding-left:0}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li:last-child{padding-right:0;border-right:none}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options.first,.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options:first-child{padding-left:0}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2{color:#999;padding-left:0;display:block;clear:none;float:left;font-family:Droid Sans,sans-serif;font-weight:700}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a{color:#999}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a:hover{color:#000}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation{float:none;clear:both;overflow:hidden;display:block;margin:0 0 10px;padding:0}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading{float:none;clear:both;overflow:hidden;display:block;margin:0;padding:0}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3{display:block;clear:none;float:left;width:auto;margin:0;padding:0;line-height:1.1em;color:#000}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path{padding-left:10px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path a{color:#000;text-decoration:none}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path a.toggleOperation.deprecated{text-decoration:line-through}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path a:hover{text-decoration:underline}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.http_method a{text-transform:uppercase;text-decoration:none;color:#fff;display:inline-block;width:50px;font-size:.7em;text-align:center;padding:7px 0 4px;border-radius:2px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span{margin:0;padding:0}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options{overflow:hidden;padding:0;display:block;clear:none;float:right;margin:6px 10px 0 0}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li{float:left;clear:none;margin:0;padding:2px 10px;font-size:.9em}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li a{text-decoration:none}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li a .markdown p{color:inherit;padding:0;line-height:inherit}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li a .nickname{color:#aaa;padding:0;line-height:inherit}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li.access{color:#000}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content{border-top:none;padding:10px;border-bottom-left-radius:6px;border-bottom-right-radius:6px;margin:0 0 20px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content h4{font-size:1.1em;margin:0;padding:15px 0 5px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header{float:none;clear:both;overflow:hidden;display:block}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header a{padding:4px 0 0 10px;display:inline-block;font-size:.9em}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header input.submit{display:block;clear:none;float:left;padding:6px 8px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header span.response_throbber{background-image:url(../images/throbber.gif);width:128px;height:16px;display:block;clear:none;float:right}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content form input[type=text].error{outline:2px solid #000;outline-color:#c00}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content form select[name=parameterContentType]{max-width:300px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.response div.block pre{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace;padding:10px;font-size:.9em;max-height:400px;overflow-y:auto}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading{background-color:#f9f2e9;border:1px solid #f0e0ca}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading h3 span.http_method a{background-color:#c5862b}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#f0e0ca;color:#c5862b}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li a{color:#c5862b}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content{background-color:#faf5ee;border:1px solid #f0e0ca}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content h4{color:#c5862b}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content div.sandbox_header a{color:#dcb67f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading{background-color:#fcffcd;border:1px solid #000;border-color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading h3 span.http_method a{text-transform:uppercase;background-color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#ffd20f;color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li a{color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content{background-color:#fcffcd;border:1px solid #000;border-color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content h4{color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content div.sandbox_header a{color:#6fc992}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading{background-color:#f5e8e8;border:1px solid #e8c6c7}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading h3 span.http_method a{text-transform:uppercase;background-color:#a41e22}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#e8c6c7;color:#a41e22}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li a{color:#a41e22}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content{background-color:#f7eded;border:1px solid #e8c6c7}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content h4{color:#a41e22}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content div.sandbox_header a{color:#c8787a}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading{background-color:#e7f6ec;border:1px solid #c3e8d1}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading h3 span.http_method a{background-color:#10a54a}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#c3e8d1;color:#10a54a}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li a{color:#10a54a}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content{background-color:#ebf7f0;border:1px solid #c3e8d1}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content h4{color:#10a54a}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content div.sandbox_header a{color:#6fc992}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading{background-color:#fce9e3;border:1px solid #f5d5c3}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading h3 span.http_method a{background-color:#d38042}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#f0cecb;color:#d38042}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li a{color:#d38042}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content{background-color:#faf0ef;border:1px solid #f0cecb}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content h4{color:#d38042}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content div.sandbox_header a{color:#dcb67f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading{background-color:#e7f0f7;border:1px solid #c3d9ec}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading h3 span.http_method a{background-color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#c3d9ec;color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li a{color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content{background-color:#ebf3f9;border:1px solid #c3d9ec}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content h4{color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content div.sandbox_header a{color:#6fa5d2}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading{background-color:#e7f0f7;border:1px solid #c3d9ec}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading h3 span.http_method a{background-color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#c3d9ec;color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading ul.options li a{color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content{background-color:#ebf3f9;border:1px solid #c3d9ec}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content h4{color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content div.sandbox_header a{color:#6fa5d2}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content{border-top:none}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li:last-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li:last-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li:last-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li:last-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li:last-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li:last-child{padding-right:0;border-right:none}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a.active,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a:active,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a:hover{text-decoration:underline}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations.first,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations:first-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li.first,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li:first-child{padding-left:0}.swagger-section .swagger-ui-wrap p#colophon{margin:0 15px 40px;padding:10px 0;font-size:.8em;border-top:1px solid #ddd;font-family:Droid Sans,sans-serif;color:#999;font-style:italic}.swagger-section .swagger-ui-wrap p#colophon a{text-decoration:none;color:#547f00}.swagger-section .swagger-ui-wrap h3{color:#000;font-size:1.1em;padding:10px 0}.swagger-section .swagger-ui-wrap .markdown ol,.swagger-section .swagger-ui-wrap .markdown ul{font-family:Droid Sans,sans-serif;margin:5px 0 10px;padding:0 0 0 18px;list-style-type:disc}.swagger-section .swagger-ui-wrap form.form_box{background-color:#ebf3f9;border:1px solid #c3d9ec;padding:10px}.swagger-section .swagger-ui-wrap form.form_box label{color:#0f6ab4!important}.swagger-section .swagger-ui-wrap form.form_box input[type=submit]{display:block;padding:10px}.swagger-section .swagger-ui-wrap form.form_box p.weak{font-size:.8em}.swagger-section .swagger-ui-wrap form.form_box p{font-size:.9em;padding:0 0 15px;color:#7e7b6d}.swagger-section .swagger-ui-wrap form.form_box p a{color:#646257}.swagger-section .swagger-ui-wrap form.form_box p strong{color:#000}.swagger-section .swagger-ui-wrap .operation-status td.markdown>p:last-child{padding-bottom:0}.swagger-section .title{font-style:bold}.swagger-section .secondary_form{display:none}.swagger-section .main_image{display:block;margin-left:auto;margin-right:auto}.swagger-section .oauth_body{margin-left:100px;margin-right:100px}.swagger-section .oauth_submit{text-align:center;display:inline-block}.swagger-section .authorize-wrapper{margin:15px 0 10px}.swagger-section .authorize-wrapper_operation{float:right}.swagger-section .authorize__btn:hover{text-decoration:underline;cursor:pointer}.swagger-section .authorize__btn_operation:hover .authorize-scopes{display:block}.swagger-section .authorize-scopes{position:absolute;margin-top:20px;background:#fff;border:1px solid #ccc;border-radius:5px;display:none;font-size:13px;max-width:300px;line-height:30px;color:#000;padding:5px}.swagger-section .authorize-scopes .authorize__scope{text-decoration:none}.swagger-section .authorize__btn_operation{height:18px;vertical-align:middle;display:inline-block;background:url(../images/explorer_icons.png) no-repeat}.swagger-section .authorize__btn_operation_login{background-position:0 0;width:18px;margin-top:-6px;margin-left:4px}.swagger-section .authorize__btn_operation_logout{background-position:-30px 0;width:18px;margin-top:-6px;margin-left:4px}.swagger-section #auth_container{color:#fff;display:inline-block;border:none;padding:5px;width:87px;height:13px}.swagger-section #auth_container .authorize__btn{color:#fff}.swagger-section .auth_container{padding:0 0 10px;margin-bottom:5px;border-bottom:1px solid #ccc;font-size:.9em}.swagger-section .auth_container .auth__title{color:#547f00;font-size:1.2em}.swagger-section .auth_container .basic_auth__label{display:inline-block;width:60px}.swagger-section .auth_container .auth__description{color:#999;margin-bottom:5px}.swagger-section .auth_container .auth__button{margin-top:10px;height:30px}.swagger-section .auth_container .key_auth__field{margin:5px 0}.swagger-section .auth_container .key_auth__label{display:inline-block;width:60px}.swagger-section .api-popup-dialog{position:absolute;display:none}.swagger-section .api-popup-dialog-wrapper{z-index:2;width:500px;background:#fff;padding:20px;border:1px solid #ccc;border-radius:5px;font-size:13px;color:#777;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%)}.swagger-section .api-popup-dialog-shadow{position:fixed;top:0;left:0;width:100%;height:100%;opacity:.2;background-color:gray;z-index:1}.swagger-section .api-popup-dialog .api-popup-title{font-size:24px;padding:10px 0}.swagger-section .api-popup-dialog .error-msg{padding-left:5px;padding-bottom:5px}.swagger-section .api-popup-dialog .api-popup-content{max-height:500px;overflow-y:auto}.swagger-section .api-popup-dialog .api-popup-authbtn,.swagger-section .api-popup-dialog .api-popup-cancel{height:30px}.swagger-section .api-popup-scopes{padding:10px 20px}.swagger-section .api-popup-scopes li{padding:5px 0;line-height:20px}.swagger-section .api-popup-scopes li input{position:relative;top:2px}.swagger-section .api-popup-scopes .api-scope-desc{padding-left:20px;font-style:italic}.swagger-section .api-popup-actions{padding-top:10px}.swagger-section fieldset{padding-bottom:10px;padding-left:20px}.swagger-section .access,.swagger-section .auth{float:right}.swagger-section .api-ic{height:18px;vertical-align:middle;display:inline-block;background:url(../images/explorer_icons.png) no-repeat}.swagger-section .api-ic .api_information_panel{position:relative;margin-top:20px;margin-left:-5px;background:#fff;border:1px solid #ccc;border-radius:5px;display:none;font-size:13px;max-width:300px;line-height:30px;color:#000;padding:5px}.swagger-section .api-ic .api_information_panel p .api-msg-enabled{color:green}.swagger-section .api-ic .api_information_panel p .api-msg-disabled{color:red}.swagger-section .api-ic:hover .api_information_panel{position:absolute;display:block}.swagger-section .ic-info{background-position:0 0;width:18px;margin-top:-6px;margin-left:4px}.swagger-section .ic-warning{background-position:-60px 0;width:18px;margin-top:-6px;margin-left:4px}.swagger-section .ic-error{background-position:-30px 0;width:18px;margin-top:-6px;margin-left:4px}.swagger-section .ic-off{background-position:-90px 0;width:58px;margin-top:-4px;cursor:pointer}.swagger-section .ic-on{background-position:-160px 0;width:58px;margin-top:-4px;cursor:pointer}.swagger-section #header{background-color:#89bf04;padding:9px 14px 19px;height:23px;min-width:775px}.swagger-section #input_baseUrl{width:400px}.swagger-section #api_selector{display:block;clear:none;float:right}.swagger-section #api_selector .input{display:inline-block;clear:none;margin:0 10px 0 0}.swagger-section #api_selector input{font-size:.9em;padding:3px;margin:0}.swagger-section #input_apiKey{width:200px}.swagger-section #auth_container .authorize__btn,.swagger-section #explore{display:block;text-decoration:none;font-weight:700;padding:6px 8px;font-size:.9em;color:#fff;background-color:#547f00;border-radius:4px}.swagger-section #auth_container .authorize__btn:hover,.swagger-section #explore:hover{background-color:#547f00}.swagger-section #header #logo{font-size:1.5em;font-weight:700;text-decoration:none;color:#fff}.swagger-section #header #logo .logo__img{display:block;float:left;margin-top:2px}.swagger-section #header #logo .logo__title{display:inline-block;padding:5px 0 0 10px}.swagger-section #content_message{margin:10px 15px;font-style:italic;color:#999}.swagger-section #message-bar{min-height:30px;text-align:center;padding-top:10px}.swagger-section .swagger-collapse:before{content:"-"}.swagger-section .swagger-expand:before{content:"+"}.swagger-section .error{outline-color:#c00;background-color:#f2dede} ================================================ FILE: apps/barrel_rest/priv/swagger/css/style.css ================================================ .swagger-section #header a#logo{font-size:1.5em;font-weight:700;text-decoration:none;padding:20px 0 20px 40px}#text-head{font-size:80px;font-family:Roboto,sans-serif;color:#fff;float:right;margin-right:20%}.navbar-fixed-top .navbar-brand,.navbar-fixed-top .navbar-nav,.navbar-header{height:auto}.navbar-inverse{background-color:#000;border-color:#000}#navbar-brand{margin-left:20%}.navtext{font-size:10px}.h1,h1{font-size:60px}.navbar-default .navbar-header .navbar-brand{color:#a2dfee}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a{color:#393939;font-family:Arvo,serif;font-size:1.5em}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a:hover{color:#000}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2{color:#525252;padding-left:0;display:block;clear:none;float:left;font-family:Arvo,serif;font-weight:700}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#0a0a0a}.container1{width:1500px;margin:auto;margin-top:0;background-repeat:no-repeat;background-position:-40px -20px;margin-bottom:210px}.container-inner{width:1200px;margin:auto;background-color:hsla(192,8%,88%,.75);padding-bottom:40px;padding-top:40px;border-radius:15px}.header-content{padding:0;width:1000px}.title1{font-size:80px;font-family:Vollkorn,serif;color:#404040;text-align:center;padding-top:40px;padding-bottom:100px}#icon{margin-top:-18px}.subtext{font-size:25px;font-style:italic;color:#08b;text-align:right;padding-right:250px}.bg-primary{background-color:#00468b}.navbar-default .nav>li>a,.navbar-default .nav>li>a:focus,.navbar-default .nav>li>a:focus:hover,.navbar-default .nav>li>a:hover{color:#08b}.text-faded{font-size:25px;font-family:Vollkorn,serif}.section-heading{font-family:Vollkorn,serif;font-size:45px;padding-bottom:10px}hr{border-color:#00468b;padding-bottom:10px}.description{margin-top:20px;padding-bottom:200px}.description li{font-family:Vollkorn,serif;font-size:25px;color:#525252;margin-left:28%;padding-top:5px}.gap{margin-top:200px}.troubleshootingtext{color:hsla(0,0%,100%,.7);padding-left:30%}.troubleshootingtext li{list-style-type:circle;font-size:25px;padding-bottom:5px}.overlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1}.block.response_body.json:hover{cursor:pointer}.backdrop{color:blue}#myModal{height:100%}.modal-backdrop{bottom:0;position:fixed}.curl{padding:10px;font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace;font-size:.9em;max-height:400px;margin-top:5px;overflow-y:auto;background-color:#fcf6db;border:1px solid #e5e0c6;border-radius:4px}.curl_title{font-size:1.1em;margin:0;padding:15px 0 5px;font-family:Open Sans,Helvetica Neue,Arial,sans-serif;font-weight:500;line-height:1.1}.footer{display:none}.swagger-section .swagger-ui-wrap h2{padding:0}h2{margin:0;margin-bottom:5px}.markdown p,.swagger-section .swagger-ui-wrap .code{font-size:15px;font-family:Arvo,serif}.swagger-section .swagger-ui-wrap b{font-family:Arvo,serif}#signin:hover{cursor:pointer}.dropdown-menu{padding:15px}.navbar-right .dropdown-menu{left:0;right:auto}#signinbutton{width:100%;height:32px;font-size:13px;font-weight:700;color:#08b}.navbar-default .nav>li .details{color:#000;text-transform:none;font-size:15px;font-weight:400;font-family:Open Sans,sans-serif;font-style:italic;line-height:20px;top:-2px}.navbar-default .nav>li .details:hover{color:#000}#signout{width:100%;height:32px;font-size:13px;font-weight:700;color:#08b} ================================================ FILE: apps/barrel_rest/priv/swagger/css/typography.css ================================================ ================================================ FILE: apps/barrel_rest/priv/swagger/index.html ================================================ Swagger UI
 
================================================ FILE: apps/barrel_rest/priv/swagger/lang/ca.js ================================================ 'use strict'; /* jshint quotmark: double */ window.SwaggerTranslator.learn({ "Warning: Deprecated":"Advertència: Obsolet", "Implementation Notes":"Notes d'implementació", "Response Class":"Classe de la Resposta", "Status":"Estatus", "Parameters":"Paràmetres", "Parameter":"Paràmetre", "Value":"Valor", "Description":"Descripció", "Parameter Type":"Tipus del Paràmetre", "Data Type":"Tipus de la Dada", "Response Messages":"Missatges de la Resposta", "HTTP Status Code":"Codi d'Estatus HTTP", "Reason":"Raó", "Response Model":"Model de la Resposta", "Request URL":"URL de la Sol·licitud", "Response Body":"Cos de la Resposta", "Response Code":"Codi de la Resposta", "Response Headers":"Capçaleres de la Resposta", "Hide Response":"Amagar Resposta", "Try it out!":"Prova-ho!", "Show/Hide":"Mostrar/Amagar", "List Operations":"Llista Operacions", "Expand Operations":"Expandir Operacions", "Raw":"Cru", "can't parse JSON. Raw result":"no puc analitzar el JSON. Resultat cru", "Example Value":"Valor d'Exemple", "Model Schema":"Esquema del Model", "Model":"Model", "apply":"aplicar", "Username":"Nom d'usuari", "Password":"Contrasenya", "Terms of service":"Termes del servei", "Created by":"Creat per", "See more at":"Veure més en", "Contact the developer":"Contactar amb el desenvolupador", "api version":"versió de la api", "Response Content Type":"Tipus de Contingut de la Resposta", "fetching resource":"recollint recurs", "fetching resource list":"recollins llista de recursos", "Explore":"Explorant", "Show Swagger Petstore Example Apis":"Mostrar API d'Exemple Swagger Petstore", "Can't read from server. It may not have the appropriate access-control-origin settings.":"No es pot llegir del servidor. Potser no teniu la configuració de control d'accés apropiada.", "Please specify the protocol for":"Si us plau, especifiqueu el protocol per a", "Can't read swagger JSON from":"No es pot llegir el JSON de swagger des de", "Finished Loading Resource Information. Rendering Swagger UI":"Finalitzada la càrrega del recurs informatiu. Renderitzant Swagger UI", "Unable to read api":"No es pot llegir l'api", "from path":"des de la ruta", "server returned":"el servidor ha retornat" }); ================================================ FILE: apps/barrel_rest/priv/swagger/lang/el.js ================================================ 'use strict'; /* jshint quotmark: double */ window.SwaggerTranslator.learn({ "Warning: Deprecated":"Προειδοποίηση: Έχει αποσυρθεί", "Implementation Notes":"Σημειώσεις Υλοποίησης", "Response Class":"Απόκριση", "Status":"Κατάσταση", "Parameters":"Παράμετροι", "Parameter":"Παράμετρος", "Value":"Τιμή", "Description":"Περιγραφή", "Parameter Type":"Τύπος Παραμέτρου", "Data Type":"Τύπος Δεδομένων", "Response Messages":"Μηνύματα Απόκρισης", "HTTP Status Code":"Κωδικός Κατάστασης HTTP", "Reason":"Αιτιολογία", "Response Model":"Μοντέλο Απόκρισης", "Request URL":"URL Αιτήματος", "Response Body":"Σώμα Απόκρισης", "Response Code":"Κωδικός Απόκρισης", "Response Headers":"Επικεφαλίδες Απόκρισης", "Hide Response":"Απόκρυψη Απόκρισης", "Headers":"Επικεφαλίδες", "Try it out!":"Δοκιμάστε το!", "Show/Hide":"Εμφάνιση/Απόκρυψη", "List Operations":"Λίστα Λειτουργιών", "Expand Operations":"Ανάπτυξη Λειτουργιών", "Raw":"Ακατέργαστο", "can't parse JSON. Raw result":"αδυναμία ανάλυσης JSON. Ακατέργαστο αποτέλεσμα", "Example Value":"Παράδειγμα Τιμής", "Model Schema":"Σχήμα Μοντέλου", "Model":"Μοντέλο", "Click to set as parameter value":"Πατήστε για να θέσετε τιμή παραμέτρου", "apply":"εφαρμογή", "Username":"Όνομα χρήση", "Password":"Κωδικός πρόσβασης", "Terms of service":"Όροι χρήσης", "Created by":"Δημιουργήθηκε από", "See more at":"Δείτε περισσότερα στο", "Contact the developer":"Επικοινωνήστε με τον προγραμματιστή", "api version":"έκδοση api", "Response Content Type":"Τύπος Περιεχομένου Απόκρισης", "Parameter content type:":"Τύπος περιεχομένου παραμέτρου:", "fetching resource":"παραλαβή πόρου", "fetching resource list":"παραλαβή λίστας πόρων", "Explore":"Εξερεύνηση", "Show Swagger Petstore Example Apis":"Εμφάνιση Api Δειγμάτων Petstore του Swagger", "Can't read from server. It may not have the appropriate access-control-origin settings.":"Αδυναμία ανάγνωσης από τον εξυπηρετητή. Μπορεί να μην έχει κατάλληλες ρυθμίσεις για access-control-origin.", "Please specify the protocol for":"Παρακαλώ προσδιορίστε το πρωτόκολλο για", "Can't read swagger JSON from":"Αδυναμία ανάγνωσης swagger JSON από", "Finished Loading Resource Information. Rendering Swagger UI":"Ολοκλήρωση Φόρτωσης Πληροφορικών Πόρου. Παρουσίαση Swagger UI", "Unable to read api":"Αδυναμία ανάγνωσης api", "from path":"από το μονοπάτι", "server returned":"ο εξυπηρετηρής επέστρεψε" }); ================================================ FILE: apps/barrel_rest/priv/swagger/lang/en.js ================================================ 'use strict'; /* jshint quotmark: double */ window.SwaggerTranslator.learn({ "Warning: Deprecated":"Warning: Deprecated", "Implementation Notes":"Implementation Notes", "Response Class":"Response Class", "Status":"Status", "Parameters":"Parameters", "Parameter":"Parameter", "Value":"Value", "Description":"Description", "Parameter Type":"Parameter Type", "Data Type":"Data Type", "Response Messages":"Response Messages", "HTTP Status Code":"HTTP Status Code", "Reason":"Reason", "Response Model":"Response Model", "Request URL":"Request URL", "Response Body":"Response Body", "Response Code":"Response Code", "Response Headers":"Response Headers", "Hide Response":"Hide Response", "Headers":"Headers", "Try it out!":"Try it out!", "Show/Hide":"Show/Hide", "List Operations":"List Operations", "Expand Operations":"Expand Operations", "Raw":"Raw", "can't parse JSON. Raw result":"can't parse JSON. Raw result", "Example Value":"Example Value", "Model Schema":"Model Schema", "Model":"Model", "Click to set as parameter value":"Click to set as parameter value", "apply":"apply", "Username":"Username", "Password":"Password", "Terms of service":"Terms of service", "Created by":"Created by", "See more at":"See more at", "Contact the developer":"Contact the developer", "api version":"api version", "Response Content Type":"Response Content Type", "Parameter content type:":"Parameter content type:", "fetching resource":"fetching resource", "fetching resource list":"fetching resource list", "Explore":"Explore", "Show Swagger Petstore Example Apis":"Show Swagger Petstore Example Apis", "Can't read from server. It may not have the appropriate access-control-origin settings.":"Can't read from server. It may not have the appropriate access-control-origin settings.", "Please specify the protocol for":"Please specify the protocol for", "Can't read swagger JSON from":"Can't read swagger JSON from", "Finished Loading Resource Information. Rendering Swagger UI":"Finished Loading Resource Information. Rendering Swagger UI", "Unable to read api":"Unable to read api", "from path":"from path", "server returned":"server returned" }); ================================================ FILE: apps/barrel_rest/priv/swagger/lang/es.js ================================================ 'use strict'; /* jshint quotmark: double */ window.SwaggerTranslator.learn({ "Warning: Deprecated":"Advertencia: Obsoleto", "Implementation Notes":"Notas de implementación", "Response Class":"Clase de la Respuesta", "Status":"Status", "Parameters":"Parámetros", "Parameter":"Parámetro", "Value":"Valor", "Description":"Descripción", "Parameter Type":"Tipo del Parámetro", "Data Type":"Tipo del Dato", "Response Messages":"Mensajes de la Respuesta", "HTTP Status Code":"Código de Status HTTP", "Reason":"Razón", "Response Model":"Modelo de la Respuesta", "Request URL":"URL de la Solicitud", "Response Body":"Cuerpo de la Respuesta", "Response Code":"Código de la Respuesta", "Response Headers":"Encabezados de la Respuesta", "Hide Response":"Ocultar Respuesta", "Try it out!":"Pruébalo!", "Show/Hide":"Mostrar/Ocultar", "List Operations":"Listar Operaciones", "Expand Operations":"Expandir Operaciones", "Raw":"Crudo", "can't parse JSON. Raw result":"no puede parsear el JSON. Resultado crudo", "Example Value":"Valor de Ejemplo", "Model Schema":"Esquema del Modelo", "Model":"Modelo", "apply":"aplicar", "Username":"Nombre de usuario", "Password":"Contraseña", "Terms of service":"Términos de Servicio", "Created by":"Creado por", "See more at":"Ver más en", "Contact the developer":"Contactar al desarrollador", "api version":"versión de la api", "Response Content Type":"Tipo de Contenido (Content Type) de la Respuesta", "fetching resource":"buscando recurso", "fetching resource list":"buscando lista del recurso", "Explore":"Explorar", "Show Swagger Petstore Example Apis":"Mostrar Api Ejemplo de Swagger Petstore", "Can't read from server. It may not have the appropriate access-control-origin settings.":"No se puede leer del servidor. Tal vez no tiene la configuración de control de acceso de origen (access-control-origin) apropiado.", "Please specify the protocol for":"Por favor, especificar el protocola para", "Can't read swagger JSON from":"No se puede leer el JSON de swagger desde", "Finished Loading Resource Information. Rendering Swagger UI":"Finalizada la carga del recurso de Información. Mostrando Swagger UI", "Unable to read api":"No se puede leer la api", "from path":"desde ruta", "server returned":"el servidor retornó" }); ================================================ FILE: apps/barrel_rest/priv/swagger/lang/fr.js ================================================ 'use strict'; /* jshint quotmark: double */ window.SwaggerTranslator.learn({ "Warning: Deprecated":"Avertissement : Obsolète", "Implementation Notes":"Notes d'implémentation", "Response Class":"Classe de la réponse", "Status":"Statut", "Parameters":"Paramètres", "Parameter":"Paramètre", "Value":"Valeur", "Description":"Description", "Parameter Type":"Type du paramètre", "Data Type":"Type de données", "Response Messages":"Messages de la réponse", "HTTP Status Code":"Code de statut HTTP", "Reason":"Raison", "Response Model":"Modèle de réponse", "Request URL":"URL appelée", "Response Body":"Corps de la réponse", "Response Code":"Code de la réponse", "Response Headers":"En-têtes de la réponse", "Hide Response":"Cacher la réponse", "Headers":"En-têtes", "Try it out!":"Testez !", "Show/Hide":"Afficher/Masquer", "List Operations":"Liste des opérations", "Expand Operations":"Développer les opérations", "Raw":"Brut", "can't parse JSON. Raw result":"impossible de décoder le JSON. Résultat brut", "Example Value":"Exemple la valeur", "Model Schema":"Définition du modèle", "Model":"Modèle", "apply":"appliquer", "Username":"Nom d'utilisateur", "Password":"Mot de passe", "Terms of service":"Conditions de service", "Created by":"Créé par", "See more at":"Voir plus sur", "Contact the developer":"Contacter le développeur", "api version":"version de l'api", "Response Content Type":"Content Type de la réponse", "fetching resource":"récupération de la ressource", "fetching resource list":"récupération de la liste de ressources", "Explore":"Explorer", "Show Swagger Petstore Example Apis":"Montrer les Apis de l'exemple Petstore de Swagger", "Can't read from server. It may not have the appropriate access-control-origin settings.":"Impossible de lire à partir du serveur. Il se peut que les réglages access-control-origin ne soient pas appropriés.", "Please specify the protocol for":"Veuillez spécifier un protocole pour", "Can't read swagger JSON from":"Impossible de lire le JSON swagger à partir de", "Finished Loading Resource Information. Rendering Swagger UI":"Chargement des informations terminé. Affichage de Swagger UI", "Unable to read api":"Impossible de lire l'api", "from path":"à partir du chemin", "server returned":"réponse du serveur" }); ================================================ FILE: apps/barrel_rest/priv/swagger/lang/geo.js ================================================ 'use strict'; /* jshint quotmark: double */ window.SwaggerTranslator.learn({ "Warning: Deprecated":"ყურადღება: აღარ გამოიყენება", "Implementation Notes":"იმპლემენტაციის აღწერა", "Response Class":"რესპონს კლასი", "Status":"სტატუსი", "Parameters":"პარამეტრები", "Parameter":"პარამეტრი", "Value":"მნიშვნელობა", "Description":"აღწერა", "Parameter Type":"პარამეტრის ტიპი", "Data Type":"მონაცემის ტიპი", "Response Messages":"პასუხი", "HTTP Status Code":"HTTP სტატუსი", "Reason":"მიზეზი", "Response Model":"რესპონს მოდელი", "Request URL":"მოთხოვნის URL", "Response Body":"პასუხის სხეული", "Response Code":"პასუხის კოდი", "Response Headers":"პასუხის ჰედერები", "Hide Response":"დამალე პასუხი", "Headers":"ჰედერები", "Try it out!":"ცადე !", "Show/Hide":"გამოჩენა/დამალვა", "List Operations":"ოპერაციების სია", "Expand Operations":"ოპერაციები ვრცლად", "Raw":"ნედლი", "can't parse JSON. Raw result":"JSON-ის დამუშავება ვერ მოხერხდა. ნედლი პასუხი", "Example Value":"მაგალითი", "Model Schema":"მოდელის სტრუქტურა", "Model":"მოდელი", "Click to set as parameter value":"პარამეტრისთვის მნიშვნელობის მისანიჭებლად, დააკლიკე", "apply":"გამოყენება", "Username":"მოხმარებელი", "Password":"პაროლი", "Terms of service":"მომსახურების პირობები", "Created by":"შექმნა", "See more at":"ნახე ვრცლად", "Contact the developer":"დაუკავშირდი დეველოპერს", "api version":"api ვერსია", "Response Content Type":"პასუხის კონტენტის ტიპი", "Parameter content type:":"პარამეტრის კონტენტის ტიპი:", "fetching resource":"რესურსების მიღება", "fetching resource list":"რესურსების სიის მიღება", "Explore":"ნახვა", "Show Swagger Petstore Example Apis":"ნახე Swagger Petstore სამაგალითო Api", "Can't read from server. It may not have the appropriate access-control-origin settings.":"სერვერთან დაკავშირება ვერ ხერხდება. შეამოწმეთ access-control-origin.", "Please specify the protocol for":"მიუთითეთ პროტოკოლი", "Can't read swagger JSON from":"swagger JSON წაკითხვა ვერ მოხერხდა", "Finished Loading Resource Information. Rendering Swagger UI":"რესურსების ჩატვირთვა სრულდება. Swagger UI რენდერდება", "Unable to read api":"api წაკითხვა ვერ მოხერხდა", "from path":"მისამართიდან", "server returned":"სერვერმა დააბრუნა" }); ================================================ FILE: apps/barrel_rest/priv/swagger/lang/it.js ================================================ 'use strict'; /* jshint quotmark: double */ window.SwaggerTranslator.learn({ "Warning: Deprecated":"Attenzione: Deprecato", "Implementation Notes":"Note di implementazione", "Response Class":"Classe della risposta", "Status":"Stato", "Parameters":"Parametri", "Parameter":"Parametro", "Value":"Valore", "Description":"Descrizione", "Parameter Type":"Tipo di parametro", "Data Type":"Tipo di dato", "Response Messages":"Messaggi della risposta", "HTTP Status Code":"Codice stato HTTP", "Reason":"Motivo", "Response Model":"Modello di risposta", "Request URL":"URL della richiesta", "Response Body":"Corpo della risposta", "Response Code":"Oggetto della risposta", "Response Headers":"Intestazioni della risposta", "Hide Response":"Nascondi risposta", "Try it out!":"Provalo!", "Show/Hide":"Mostra/Nascondi", "List Operations":"Mostra operazioni", "Expand Operations":"Espandi operazioni", "Raw":"Grezzo (raw)", "can't parse JSON. Raw result":"non è possibile parsare il JSON. Risultato grezzo (raw).", "Model Schema":"Schema del modello", "Model":"Modello", "apply":"applica", "Username":"Nome utente", "Password":"Password", "Terms of service":"Condizioni del servizio", "Created by":"Creato da", "See more at":"Informazioni aggiuntive:", "Contact the developer":"Contatta lo sviluppatore", "api version":"versione api", "Response Content Type":"Tipo di contenuto (content type) della risposta", "fetching resource":"recuperando la risorsa", "fetching resource list":"recuperando lista risorse", "Explore":"Esplora", "Show Swagger Petstore Example Apis":"Mostra le api di esempio di Swagger Petstore", "Can't read from server. It may not have the appropriate access-control-origin settings.":"Non è possibile leggere dal server. Potrebbe non avere le impostazioni di controllo accesso origine (access-control-origin) appropriate.", "Please specify the protocol for":"Si prega di specificare il protocollo per", "Can't read swagger JSON from":"Impossibile leggere JSON swagger da:", "Finished Loading Resource Information. Rendering Swagger UI":"Lettura informazioni risorse termianta. Swagger UI viene mostrata", "Unable to read api":"Impossibile leggere la api", "from path":"da cartella", "server returned":"il server ha restituito" }); ================================================ FILE: apps/barrel_rest/priv/swagger/lang/ja.js ================================================ 'use strict'; /* jshint quotmark: double */ window.SwaggerTranslator.learn({ "Warning: Deprecated":"警告: 廃止予定", "Implementation Notes":"実装メモ", "Response Class":"レスポンスクラス", "Status":"ステータス", "Parameters":"パラメータ群", "Parameter":"パラメータ", "Value":"値", "Description":"説明", "Parameter Type":"パラメータタイプ", "Data Type":"データタイプ", "Response Messages":"レスポンスメッセージ", "HTTP Status Code":"HTTPステータスコード", "Reason":"理由", "Response Model":"レスポンスモデル", "Request URL":"リクエストURL", "Response Body":"レスポンスボディ", "Response Code":"レスポンスコード", "Response Headers":"レスポンスヘッダ", "Hide Response":"レスポンスを隠す", "Headers":"ヘッダ", "Try it out!":"実際に実行!", "Show/Hide":"表示/非表示", "List Operations":"操作一覧", "Expand Operations":"操作の展開", "Raw":"未加工", "can't parse JSON. Raw result":"JSONへ解釈できません. 未加工の結果", "Example Value":"値の例", "Model Schema":"モデルスキーマ", "Model":"モデル", "Click to set as parameter value":"パラメータ値と設定するにはクリック", "apply":"実行", "Username":"ユーザ名", "Password":"パスワード", "Terms of service":"サービス利用規約", "Created by":"Created by", "See more at":"詳細を見る", "Contact the developer":"開発者に連絡", "api version":"APIバージョン", "Response Content Type":"レスポンス コンテンツタイプ", "Parameter content type:":"パラメータコンテンツタイプ:", "fetching resource":"リソースの取得", "fetching resource list":"リソース一覧の取得", "Explore":"調査", "Show Swagger Petstore Example Apis":"SwaggerペットストアAPIの表示", "Can't read from server. It may not have the appropriate access-control-origin settings.":"サーバから読み込めません. 適切なaccess-control-origin設定を持っていない可能性があります.", "Please specify the protocol for":"プロトコルを指定してください", "Can't read swagger JSON from":"次からswagger JSONを読み込めません", "Finished Loading Resource Information. Rendering Swagger UI":"リソース情報の読み込みが完了しました. Swagger UIを描画しています", "Unable to read api":"APIを読み込めません", "from path":"次のパスから", "server returned":"サーバからの返答" }); ================================================ FILE: apps/barrel_rest/priv/swagger/lang/ko-kr.js ================================================ 'use strict'; /* jshint quotmark: double */ window.SwaggerTranslator.learn({ "Warning: Deprecated":"경고:폐기예정됨", "Implementation Notes":"구현 노트", "Response Class":"응답 클래스", "Status":"상태", "Parameters":"매개변수들", "Parameter":"매개변수", "Value":"값", "Description":"설명", "Parameter Type":"매개변수 타입", "Data Type":"데이터 타입", "Response Messages":"응답 메세지", "HTTP Status Code":"HTTP 상태 코드", "Reason":"원인", "Response Model":"응답 모델", "Request URL":"요청 URL", "Response Body":"응답 본문", "Response Code":"응답 코드", "Response Headers":"응답 헤더", "Hide Response":"응답 숨기기", "Headers":"헤더", "Try it out!":"써보기!", "Show/Hide":"보이기/숨기기", "List Operations":"목록 작업", "Expand Operations":"전개 작업", "Raw":"원본", "can't parse JSON. Raw result":"JSON을 파싱할수 없음. 원본결과:", "Model Schema":"모델 스키마", "Model":"모델", "apply":"적용", "Username":"사용자 이름", "Password":"암호", "Terms of service":"이용약관", "Created by":"작성자", "See more at":"추가정보:", "Contact the developer":"개발자에게 문의", "api version":"api버전", "Response Content Type":"응답Content Type", "fetching resource":"리소스 가져오기", "fetching resource list":"리소스 목록 가져오기", "Explore":"탐색", "Show Swagger Petstore Example Apis":"Swagger Petstore 예제 보기", "Can't read from server. It may not have the appropriate access-control-origin settings.":"서버로부터 읽어들일수 없습니다. access-control-origin 설정이 올바르지 않을수 있습니다.", "Please specify the protocol for":"다음을 위한 프로토콜을 정하세요", "Can't read swagger JSON from":"swagger JSON 을 다음으로 부터 읽을수 없습니다", "Finished Loading Resource Information. Rendering Swagger UI":"리소스 정보 불러오기 완료. Swagger UI 랜더링", "Unable to read api":"api를 읽을 수 없습니다.", "from path":"다음 경로로 부터", "server returned":"서버 응답함." }); ================================================ FILE: apps/barrel_rest/priv/swagger/lang/pl.js ================================================ 'use strict'; /* jshint quotmark: double */ window.SwaggerTranslator.learn({ "Warning: Deprecated":"Uwaga: Wycofane", "Implementation Notes":"Uwagi Implementacji", "Response Class":"Klasa Odpowiedzi", "Status":"Status", "Parameters":"Parametry", "Parameter":"Parametr", "Value":"Wartość", "Description":"Opis", "Parameter Type":"Typ Parametru", "Data Type":"Typ Danych", "Response Messages":"Wiadomości Odpowiedzi", "HTTP Status Code":"Kod Statusu HTTP", "Reason":"Przyczyna", "Response Model":"Model Odpowiedzi", "Request URL":"URL Wywołania", "Response Body":"Treść Odpowiedzi", "Response Code":"Kod Odpowiedzi", "Response Headers":"Nagłówki Odpowiedzi", "Hide Response":"Ukryj Odpowiedź", "Headers":"Nagłówki", "Try it out!":"Wypróbuj!", "Show/Hide":"Pokaż/Ukryj", "List Operations":"Lista Operacji", "Expand Operations":"Rozwiń Operacje", "Raw":"Nieprzetworzone", "can't parse JSON. Raw result":"nie można przetworzyć pliku JSON. Nieprzetworzone dane", "Model Schema":"Schemat Modelu", "Model":"Model", "apply":"użyj", "Username":"Nazwa użytkownika", "Password":"Hasło", "Terms of service":"Warunki używania", "Created by":"Utworzone przez", "See more at":"Zobacz więcej na", "Contact the developer":"Kontakt z deweloperem", "api version":"wersja api", "Response Content Type":"Typ Zasobu Odpowiedzi", "fetching resource":"ładowanie zasobu", "fetching resource list":"ładowanie listy zasobów", "Explore":"Eksploruj", "Show Swagger Petstore Example Apis":"Pokaż Przykładowe Api Swagger Petstore", "Can't read from server. It may not have the appropriate access-control-origin settings.":"Brak połączenia z serwerem. Może on nie mieć odpowiednich ustawień access-control-origin.", "Please specify the protocol for":"Proszę podać protokół dla", "Can't read swagger JSON from":"Nie można odczytać swagger JSON z", "Finished Loading Resource Information. Rendering Swagger UI":"Ukończono Ładowanie Informacji o Zasobie. Renderowanie Swagger UI", "Unable to read api":"Nie można odczytać api", "from path":"ze ścieżki", "server returned":"serwer zwrócił" }); ================================================ FILE: apps/barrel_rest/priv/swagger/lang/pt.js ================================================ 'use strict'; /* jshint quotmark: double */ window.SwaggerTranslator.learn({ "Warning: Deprecated":"Aviso: Depreciado", "Implementation Notes":"Notas de Implementação", "Response Class":"Classe de resposta", "Status":"Status", "Parameters":"Parâmetros", "Parameter":"Parâmetro", "Value":"Valor", "Description":"Descrição", "Parameter Type":"Tipo de parâmetro", "Data Type":"Tipo de dados", "Response Messages":"Mensagens de resposta", "HTTP Status Code":"Código de status HTTP", "Reason":"Razão", "Response Model":"Modelo resposta", "Request URL":"URL requisição", "Response Body":"Corpo da resposta", "Response Code":"Código da resposta", "Response Headers":"Cabeçalho da resposta", "Headers":"Cabeçalhos", "Hide Response":"Esconder resposta", "Try it out!":"Tente agora!", "Show/Hide":"Mostrar/Esconder", "List Operations":"Listar operações", "Expand Operations":"Expandir operações", "Raw":"Cru", "can't parse JSON. Raw result":"Falha ao analisar JSON. Resulto cru", "Model Schema":"Modelo esquema", "Model":"Modelo", "apply":"Aplicar", "Username":"Usuário", "Password":"Senha", "Terms of service":"Termos do serviço", "Created by":"Criado por", "See more at":"Veja mais em", "Contact the developer":"Contate o desenvolvedor", "api version":"Versão api", "Response Content Type":"Tipo de conteúdo da resposta", "fetching resource":"busca recurso", "fetching resource list":"buscando lista de recursos", "Explore":"Explorar", "Show Swagger Petstore Example Apis":"Show Swagger Petstore Example Apis", "Can't read from server. It may not have the appropriate access-control-origin settings.":"Não é possível ler do servidor. Pode não ter as apropriadas configurações access-control-origin", "Please specify the protocol for":"Por favor especifique o protocolo", "Can't read swagger JSON from":"Não é possível ler o JSON Swagger de", "Finished Loading Resource Information. Rendering Swagger UI":"Carregar informação de recurso finalizada. Renderizando Swagger UI", "Unable to read api":"Não foi possível ler api", "from path":"do caminho", "server returned":"servidor retornou" }); ================================================ FILE: apps/barrel_rest/priv/swagger/lang/ru.js ================================================ 'use strict'; /* jshint quotmark: double */ window.SwaggerTranslator.learn({ "Warning: Deprecated":"Предупреждение: Устарело", "Implementation Notes":"Заметки", "Response Class":"Пример ответа", "Status":"Статус", "Parameters":"Параметры", "Parameter":"Параметр", "Value":"Значение", "Description":"Описание", "Parameter Type":"Тип параметра", "Data Type":"Тип данных", "HTTP Status Code":"HTTP код", "Reason":"Причина", "Response Model":"Структура ответа", "Request URL":"URL запроса", "Response Body":"Тело ответа", "Response Code":"HTTP код ответа", "Response Headers":"Заголовки ответа", "Hide Response":"Спрятать ответ", "Headers":"Заголовки", "Response Messages":"Что может прийти в ответ", "Try it out!":"Попробовать!", "Show/Hide":"Показать/Скрыть", "List Operations":"Операции кратко", "Expand Operations":"Операции подробно", "Raw":"В сыром виде", "can't parse JSON. Raw result":"Не удается распарсить ответ:", "Example Value":"Пример", "Model Schema":"Структура", "Model":"Описание", "Click to set as parameter value":"Нажмите, чтобы испльзовать в качестве значения параметра", "apply":"применить", "Username":"Имя пользователя", "Password":"Пароль", "Terms of service":"Условия использования", "Created by":"Разработано", "See more at":"Еще тут", "Contact the developer":"Связаться с разработчиком", "api version":"Версия API", "Response Content Type":"Content Type ответа", "Parameter content type:":"Content Type параметра:", "fetching resource":"Получение ресурса", "fetching resource list":"Получение ресурсов", "Explore":"Показать", "Show Swagger Petstore Example Apis":"Показать примеры АПИ", "Can't read from server. It may not have the appropriate access-control-origin settings.":"Не удается получить ответ от сервера. Возможно, проблема с настройками доступа", "Please specify the protocol for":"Пожалуйста, укажите протокол для", "Can't read swagger JSON from":"Не получается прочитать swagger json из", "Finished Loading Resource Information. Rendering Swagger UI":"Загрузка информации о ресурсах завершена. Рендерим", "Unable to read api":"Не удалось прочитать api", "from path":"по адресу", "server returned":"сервер сказал" }); ================================================ FILE: apps/barrel_rest/priv/swagger/lang/tr.js ================================================ 'use strict'; /* jshint quotmark: double */ window.SwaggerTranslator.learn({ "Warning: Deprecated":"Uyarı: Deprecated", "Implementation Notes":"Gerçekleştirim Notları", "Response Class":"Dönen Sınıf", "Status":"Statü", "Parameters":"Parametreler", "Parameter":"Parametre", "Value":"Değer", "Description":"Açıklama", "Parameter Type":"Parametre Tipi", "Data Type":"Veri Tipi", "Response Messages":"Dönüş Mesajı", "HTTP Status Code":"HTTP Statü Kodu", "Reason":"Gerekçe", "Response Model":"Dönüş Modeli", "Request URL":"İstek URL", "Response Body":"Dönüş İçeriği", "Response Code":"Dönüş Kodu", "Response Headers":"Dönüş Üst Bilgileri", "Hide Response":"Dönüşü Gizle", "Headers":"Üst Bilgiler", "Try it out!":"Dene!", "Show/Hide":"Göster/Gizle", "List Operations":"Operasyonları Listele", "Expand Operations":"Operasyonları Aç", "Raw":"Ham", "can't parse JSON. Raw result":"JSON çözümlenemiyor. Ham sonuç", "Model Schema":"Model Şema", "Model":"Model", "apply":"uygula", "Username":"Kullanıcı Adı", "Password":"Parola", "Terms of service":"Servis şartları", "Created by":"Oluşturan", "See more at":"Daha fazlası için", "Contact the developer":"Geliştirici ile İletişime Geçin", "api version":"api versiyon", "Response Content Type":"Dönüş İçerik Tipi", "fetching resource":"kaynak getiriliyor", "fetching resource list":"kaynak listesi getiriliyor", "Explore":"Keşfet", "Show Swagger Petstore Example Apis":"Swagger Petstore Örnek Api'yi Gör", "Can't read from server. It may not have the appropriate access-control-origin settings.":"Sunucudan okuma yapılamıyor. Sunucu access-control-origin ayarlarınızı kontrol edin.", "Please specify the protocol for":"Lütfen istenen adres için protokol belirtiniz", "Can't read swagger JSON from":"Swagger JSON bu kaynaktan okunamıyor", "Finished Loading Resource Information. Rendering Swagger UI":"Kaynak baglantısı tamamlandı. Swagger UI gösterime hazırlanıyor", "Unable to read api":"api okunamadı", "from path":"yoldan", "server returned":"sunucuya dönüldü" }); ================================================ FILE: apps/barrel_rest/priv/swagger/lang/translator.js ================================================ 'use strict'; /** * Translator for documentation pages. * * To enable translation you should include one of language-files in your index.html * after . * For example - * * If you wish to translate some new texts you should do two things: * 1. Add a new phrase pair ("New Phrase": "New Translation") into your language file (for example lang/ru.js). It will be great if you add it in other language files too. * 2. Mark that text it templates this way New Phrase or . * The main thing here is attribute data-sw-translate. Only inner html, title-attribute and value-attribute are going to translate. * */ window.SwaggerTranslator = { _words:[], translate: function(sel) { var $this = this; sel = sel || '[data-sw-translate]'; $(sel).each(function() { $(this).html($this._tryTranslate($(this).html())); $(this).val($this._tryTranslate($(this).val())); $(this).attr('title', $this._tryTranslate($(this).attr('title'))); }); }, _tryTranslate: function(word) { return this._words[$.trim(word)] !== undefined ? this._words[$.trim(word)] : word; }, learn: function(wordsMap) { this._words = wordsMap; } }; ================================================ FILE: apps/barrel_rest/priv/swagger/lang/zh-cn.js ================================================ 'use strict'; /* jshint quotmark: double */ window.SwaggerTranslator.learn({ "Warning: Deprecated":"警告:已过时", "Implementation Notes":"实现备注", "Response Class":"响应类", "Status":"状态", "Parameters":"参数", "Parameter":"参数", "Value":"值", "Description":"描述", "Parameter Type":"参数类型", "Data Type":"数据类型", "Response Messages":"响应消息", "HTTP Status Code":"HTTP状态码", "Reason":"原因", "Response Model":"响应模型", "Request URL":"请求URL", "Response Body":"响应体", "Response Code":"响应码", "Response Headers":"响应头", "Hide Response":"隐藏响应", "Headers":"头", "Try it out!":"试一下!", "Show/Hide":"显示/隐藏", "List Operations":"显示操作", "Expand Operations":"展开操作", "Raw":"原始", "can't parse JSON. Raw result":"无法解析JSON. 原始结果", "Example Value":"示例", "Click to set as parameter value":"点击设置参数", "Model Schema":"模型架构", "Model":"模型", "apply":"应用", "Username":"用户名", "Password":"密码", "Terms of service":"服务条款", "Created by":"创建者", "See more at":"查看更多:", "Contact the developer":"联系开发者", "api version":"api版本", "Response Content Type":"响应Content Type", "Parameter content type:":"参数类型:", "fetching resource":"正在获取资源", "fetching resource list":"正在获取资源列表", "Explore":"浏览", "Show Swagger Petstore Example Apis":"显示 Swagger Petstore 示例 Apis", "Can't read from server. It may not have the appropriate access-control-origin settings.":"无法从服务器读取。可能没有正确设置access-control-origin。", "Please specify the protocol for":"请指定协议:", "Can't read swagger JSON from":"无法读取swagger JSON于", "Finished Loading Resource Information. Rendering Swagger UI":"已加载资源信息。正在渲染Swagger UI", "Unable to read api":"无法读取api", "from path":"从路径", "server returned":"服务器返回" }); ================================================ FILE: apps/barrel_rest/priv/swagger/lib/backbone-min.js ================================================ !function(t,e){if("function"==typeof define&&define.amd)define(["underscore","jquery","exports"],function(i,n,s){t.Backbone=e(t,s,i,n)});else if("undefined"!=typeof exports){var i=require("underscore");e(t,exports,i)}else t.Backbone=e(t,{},t._,t.jQuery||t.Zepto||t.ender||t.$)}(this,function(t,e,i,n){var s=t.Backbone,r=[],a=(r.push,r.slice);r.splice;e.VERSION="1.1.2",e.$=n,e.noConflict=function(){return t.Backbone=s,this},e.emulateHTTP=!1,e.emulateJSON=!1;var o=e.Events={on:function(t,e,i){if(!c(this,"on",t,[e,i])||!e)return this;this._events||(this._events={});var n=this._events[t]||(this._events[t]=[]);return n.push({callback:e,context:i,ctx:i||this}),this},once:function(t,e,n){if(!c(this,"once",t,[e,n])||!e)return this;var s=this,r=i.once(function(){s.off(t,r),e.apply(this,arguments)});return r._callback=e,this.on(t,r,n)},off:function(t,e,n){var s,r,a,o,h,u,l,d;if(!this._events||!c(this,"off",t,[e,n]))return this;if(!t&&!e&&!n)return this._events=void 0,this;for(o=t?[t]:i.keys(this._events),h=0,u=o.length;h").attr(t);this.setElement(n,!1)}}}),e.sync=function(t,n,s){var r=E[t];i.defaults(s||(s={}),{emulateHTTP:e.emulateHTTP,emulateJSON:e.emulateJSON});var a={type:r,dataType:"json"};if(s.url||(a.url=i.result(n,"url")||j()),null!=s.data||!n||"create"!==t&&"update"!==t&&"patch"!==t||(a.contentType="application/json",a.data=JSON.stringify(s.attrs||n.toJSON(s))),s.emulateJSON&&(a.contentType="application/x-www-form-urlencoded",a.data=a.data?{model:a.data}:{}),s.emulateHTTP&&("PUT"===r||"DELETE"===r||"PATCH"===r)){a.type="POST",s.emulateJSON&&(a.data._method=r);var o=s.beforeSend;s.beforeSend=function(t){if(t.setRequestHeader("X-HTTP-Method-Override",r),o)return o.apply(this,arguments)}}"GET"===a.type||s.emulateJSON||(a.processData=!1),"PATCH"===a.type&&x&&(a.xhr=function(){return new ActiveXObject("Microsoft.XMLHTTP")});var h=s.xhr=e.ajax(i.extend(a,s));return n.trigger("request",n,h,s),h};var x=!("undefined"==typeof window||!window.ActiveXObject||window.XMLHttpRequest&&(new XMLHttpRequest).dispatchEvent),E={create:"POST",update:"PUT",patch:"PATCH","delete":"DELETE",read:"GET"};e.ajax=function(){return e.$.ajax.apply(e.$,arguments)};var k=e.Router=function(t){t||(t={}),t.routes&&(this.routes=t.routes),this._bindRoutes(),this.initialize.apply(this,arguments)},T=/\((.*?)\)/g,$=/(\(\?)?:\w+/g,S=/\*\w+/g,H=/[\-{}\[\]+?.,\\\^$|#\s]/g;i.extend(k.prototype,o,{initialize:function(){},route:function(t,n,s){i.isRegExp(t)||(t=this._routeToRegExp(t)),i.isFunction(n)&&(s=n,n=""),s||(s=this[n]);var r=this;return e.history.route(t,function(i){var a=r._extractParameters(t,i);r.execute(s,a),r.trigger.apply(r,["route:"+n].concat(a)),r.trigger("route",n,a),e.history.trigger("route",r,n,a)}),this},execute:function(t,e){t&&t.apply(this,e)},navigate:function(t,i){return e.history.navigate(t,i),this},_bindRoutes:function(){if(this.routes){this.routes=i.result(this,"routes");for(var t,e=i.keys(this.routes);null!=(t=e.pop());)this.route(t,this.routes[t])}},_routeToRegExp:function(t){return t=t.replace(H,"\\$&").replace(T,"(?:$1)?").replace($,function(t,e){return e?t:"([^/?]+)"}).replace(S,"([^?]*?)"),new RegExp("^"+t+"(?:\\?([\\s\\S]*))?$")},_extractParameters:function(t,e){var n=t.exec(e).slice(1);return i.map(n,function(t,e){return e===n.length-1?t||null:t?decodeURIComponent(t):null})}});var A=e.History=function(){this.handlers=[],i.bindAll(this,"checkUrl"),"undefined"!=typeof window&&(this.location=window.location,this.history=window.history)},I=/^[#\/]|\s+$/g,N=/^\/+|\/+$/g,R=/msie [\w.]+/,O=/\/$/,P=/#.*$/;A.started=!1,i.extend(A.prototype,o,{interval:50,atRoot:function(){return this.location.pathname.replace(/[^\/]$/,"$&/")===this.root},getHash:function(t){var e=(t||this).location.href.match(/#(.*)$/);return e?e[1]:""},getFragment:function(t,e){if(null==t)if(this._hasPushState||!this._wantsHashChange||e){t=decodeURI(this.location.pathname+this.location.search);var i=this.root.replace(O,"");t.indexOf(i)||(t=t.slice(i.length))}else t=this.getHash();return t.replace(I,"")},start:function(t){if(A.started)throw new Error("Backbone.history has already been started");A.started=!0,this.options=i.extend({root:"/"},this.options,t),this.root=this.options.root,this._wantsHashChange=this.options.hashChange!==!1,this._wantsPushState=!!this.options.pushState,this._hasPushState=!!(this.options.pushState&&this.history&&this.history.pushState);var n=this.getFragment(),s=document.documentMode,r=R.exec(navigator.userAgent.toLowerCase())&&(!s||s<=7);if(this.root=("/"+this.root+"/").replace(N,"/"),r&&this._wantsHashChange){var a=e.$('