Full Code of barrel-db/barrel-platform for AI

master f55fdb311d1b cached
104 files
3.1 MB
813.2k tokens
671 symbols
1 requests
Download .txt
Showing preview only (3,262K chars total). Download the full file or copy to clipboard to get everything.
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
================================================

<img src="https://raw.githubusercontent.com/barrel-db/media/master/banner/barrel-banner-groupfb.png">

<p align="center">


   <a href="https://gitter.im/barrel-db/barrel-platform?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge">
        <img src="https://badges.gitter.im/barrel-db/barrel-platform.svg">
    </a>

   <a href="https://gitlab.com/barrel-db/barrel-platform/commits/master">
        <img alt="build status" src="https://gitlab.com/barrel-db/barrel-platform/badges/master/build.svg" />
    </a>

   <a href="https://github.com/barrel-db/barrel-platform/blob/master/LICENSE">
        <img src="https://img.shields.io/badge/license-Apache--2.0-blue.svg">
   </a>

   <a href="https://twitter.com/barreldb">
        <img src="https://img.shields.io/badge/twitter-%40barreldb-55acee.svg">
   </a>
</p>

<p align="center"><i>A document-oriented database targeting data locality & P2P</i> - <a href="https://barrel-db.org/" target="_blank">barrel-db.org</a></p>

# 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 <bchesneau@gmail.com>.
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, <COMPANY>
%%% @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, <COMPANY>
%%% @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, <COMPANY>
%%% @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))>> || <<H:4,L:4>> <= 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) -> <<Acc/binary, Sep/binary, (to_binary(Value))/binary>> 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(<<Codepoint/utf8, Rest/binary>>, []) ->
  decode_path(Rest, [<< Codepoint/utf8 >>]);
decode_path(<<Codepoint/utf8, Rest/binary>>, [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 <bchesneau@gmail.com>.
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 .sw
Download .txt
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
Download .txt
SYMBOL INDEX (671 symbols across 5 files)

FILE: apps/barrel_rest/priv/swagger/lib/handlebars-4.0.5.js
  function e (line 1) | function e(s){if(r[s])return r[s].exports;var i=r[s]={exports:{},id:s,lo...
  function s (line 1) | function s(){var t=v();return t.compile=function(e,r){return l.compile(e...
  function s (line 1) | function s(){var t=new o.HandlebarsEnvironment;return f.extend(t,o),t.Sa...
  function s (line 1) | function s(t,e,r){this.helpers=t||{},this.partials=e||{},this.decorators...
  function r (line 1) | function r(t){return l[t]}
  function s (line 1) | function s(t){for(var e=1;e<arguments.length;e++)for(var r in arguments[...
  function i (line 1) | function i(t,e){for(var r=0,s=t.length;r<s;r++)if(t[r]===e)return r;retu...
  function a (line 1) | function a(t){if("string"!=typeof t){if(t&&t.toHTML)return t.toHTML();if...
  function n (line 1) | function n(t){return!t&&0!==t||!(!m(t)||0!==t.length)}
  function o (line 1) | function o(t){var e=s({},t);return e._parent=t,e}
  function c (line 1) | function c(t,e){return t.path=e,t}
  function h (line 1) | function h(t,e){return(t?t+".":"")+e}
  function r (line 1) | function r(t,e){var i=e&&e.loc,a=void 0,n=void 0;i&&(a=i.start.line,n=i....
  function s (line 1) | function s(t){n["default"](t),c["default"](t),l["default"](t),u["default...
  function r (line 1) | function r(e,r,a){h&&(h.key=e,h.index=r,h.first=0===r,h.last=!!a,l&&(h.c...
  function s (line 1) | function s(t){n["default"](t)}
  function r (line 1) | function r(t){this.string=t}
  function s (line 1) | function s(t){var e=t&&t[0]||1,r=v.COMPILER_REVISION;if(e!==r){if(e<r){v...
  function i (line 1) | function i(t,e){function r(r,s,i){i.hash&&(s=d.extend({},s,i.hash),i.ids...
  function a (line 1) | function a(t,e,r,s,i,a,n){function o(e){var i=arguments.length<=1||void ...
  function n (line 1) | function n(t,e,r){return t?t.call||r.name||(r.name=t,t=r.partials[t]):t=...
  function o (line 1) | function o(t,e,r){r.partial=!0,r.ids&&(r.data.contextPath=r.ids[0]||r.da...
  function c (line 1) | function c(){return""}
  function h (line 1) | function h(t,e){return e&&"root"in e||(e=e?v.createFrame(e):{},e.root=t),e}
  function l (line 1) | function l(t,e,r,s,i,a){if(t.decorator){var n={};e=t.decorator(e,n,r,s&&...
  function s (line 1) | function s(t,e){if("Program"===t.type)return t;o["default"].yy=f,f.locIn...
  function t (line 1) | function t(){this.yy={}}
  function e (line 2) | function e(){var t;return t=r.lexer.lex()||1,"number"!=typeof t&&(t=r.sy...
  function i (line 2) | function i(t,r){return e.yytext=e.yytext.substr(t,e.yyleng-r)}
  function s (line 2) | function s(){var t=arguments.length<=0||void 0===arguments[0]?{}:argumen...
  function i (line 2) | function i(t,e,r){void 0===e&&(e=t.length);var s=t[e-1],i=t[e-2];return ...
  function a (line 2) | function a(t,e,r){void 0===e&&(e=-1);var s=t[e+1],i=t[e+2];return s?"Con...
  function n (line 2) | function n(t,e,r){var s=t[null==e?0:e+1];if(s&&"ContentStatement"===s.ty...
  function o (line 2) | function o(t,e,r){var s=t[null==e?t.length-1:e-1];if(s&&"ContentStatemen...
  function s (line 2) | function s(){this.parents=[]}
  function i (line 2) | function i(t){this.acceptRequired(t,"path"),this.acceptArray(t.params),t...
  function a (line 2) | function a(t){i.call(this,t),this.acceptKey(t,"program"),this.acceptKey(...
  function n (line 2) | function n(t){this.acceptRequired(t,"name"),this.acceptArray(t.params),t...
  function s (line 2) | function s(t,e){if(e=e.path?e.path.original:e,t.path.original!==e){var r...
  function i (line 2) | function i(t,e){this.source=t,this.start={line:e.first_line,column:e.fir...
  function a (line 2) | function a(t){return/^\[.*\]$/.test(t)?t.substr(1,t.length-2):t}
  function n (line 2) | function n(t,e){return{open:"~"===t.charAt(2),close:"~"===e.charAt(e.len...
  function o (line 2) | function o(t){return t.replace(/^\{\{~?\!-?-?/,"").replace(/-?-?~?\}\}$/...
  function c (line 2) | function c(t,e,r){r=this.locInfo(r);for(var s=t?"@":"",i=[],a=0,n="",o=0...
  function h (line 2) | function h(t,e,r,s,i,a){var n=s.charAt(3)||s.charAt(2),o="{"!==n&&"&"!==...
  function l (line 2) | function l(t,e,r,i){s(t,r),i=this.locInfo(i);var a={type:"Program",body:...
  function p (line 2) | function p(t,e,r,i,a,n){i&&i.path&&s(t,i);var o=/\*/.test(t.open);e.bloc...
  function u (line 2) | function u(t,e){if(!e&&t.length){var r=t[0].loc,s=t[t.length-1].loc;r&&s...
  function f (line 2) | function f(t,e,r,i){return s(t,r),{type:"PartialBlockStatement",name:t.p...
  function s (line 2) | function s(){}
  function i (line 2) | function i(t,e,r){if(null==t||"string"!=typeof t&&"Program"!==t.type)thr...
  function a (line 2) | function a(t,e,r){function s(){var s=r.parse(t,e),i=(new r.Compiler).com...
  function n (line 2) | function n(t,e){if(t===e)return!0;if(p.isArray(t)&&p.isArray(e)&&t.lengt...
  function o (line 2) | function o(t){if(!t.path.parts){var e=t.path;t.path={type:"PathExpressio...
  function s (line 2) | function s(t){this.value=t}
  function i (line 2) | function i(){}
  function a (line 2) | function a(t,e,r,s){var i=e.popStack(),a=0,n=r.length;for(t&&n--;a<n;a++...
  function s (line 3) | function s(t,e,r){if(a.isArray(t)){for(var s=[],i=0,n=t.length;i<n;i++)s...
  function i (line 3) | function i(t){this.srcFile=t,this.source=[]}

FILE: apps/barrel_rest/priv/swagger/lib/highlight.9.1.0.pack.js
  function r (line 1) | function r(e){return e.replace(/&/gm,"&amp;").replace(/</gm,"&lt;").repl...
  function t (line 1) | function t(e){return e.nodeName.toLowerCase()}
  function n (line 1) | function n(e,r){var t=e&&e.exec(r);return t&&0==t.index}
  function a (line 1) | function a(e){return/^(no-?highlight|plain|text)$/i.test(e)}
  function c (line 1) | function c(e){var r,t,n,c=e.className+" ";if(c+=e.parentNode?e.parentNod...
  function i (line 1) | function i(e,r){var t,n={};for(t in e)n[t]=e[t];if(r)for(t in r)n[t]=r[t...
  function o (line 1) | function o(e){var r=[];return function n(e,a){for(var c=e.firstChild;c;c...
  function s (line 1) | function s(e,n,a){function c(){return e.length&&n.length?e[0].offset!=n[...
  function u (line 1) | function u(e){function r(e){return e&&e.source||e}function t(t,n){return...
  function l (line 1) | function l(e,t,a,c){function i(e,r){for(var t=0;t<r.c.length;t++)if(n(r....
  function f (line 1) | function f(e,t){t=t||w.languages||Object.keys(y);var n={r:0,value:r(e)},...
  function b (line 1) | function b(e){return w.tabReplace&&(e=e.replace(/^((<[^>]+>|\t)+)/gm,fun...
  function g (line 1) | function g(e,r,t){var n=r?C[r]:t,a=[e.trim()];return e.match(/\bhljs\b/)...
  function p (line 1) | function p(e){var r=c(e);if(!a(r)){var t;w.useBR?(t=document.createEleme...
  function h (line 1) | function h(e){w=i(w,e)}
  function d (line 1) | function d(){if(!d.called){d.called=!0;var e=document.querySelectorAll("...
  function m (line 1) | function m(){addEventListener("DOMContentLoaded",d,!1),addEventListener(...
  function v (line 1) | function v(r,t){var n=y[r]=t(e);n.aliases&&n.aliases.forEach(function(e)...
  function N (line 1) | function N(){return Object.keys(y)}
  function E (line 1) | function E(e){return e=(e||"").toLowerCase(),y[e]||y[C[e]]}

FILE: apps/barrel_rest/priv/swagger/lib/marked.js
  function e (line 1) | function e(e){this.tokens=[],this.tokens.links={},this.options=e||a.defa...
  function t (line 1) | function t(e,t){if(this.options=t||a.defaults,this.links=e,this.rules=u....
  function n (line 1) | function n(e){this.options=e||{}}
  function r (line 1) | function r(e){this.tokens=[],this.token=null,this.options=e||a.defaults,...
  function s (line 1) | function s(e,t){return e.replace(t?/&/g:/&(?!#?\w+;)/g,"&amp;").replace(...
  function i (line 1) | function i(e){return e.replace(/&([#\w]+);/g,function(e,t){return t=t.to...
  function l (line 1) | function l(e,t){return e=e.source,t=t||"",function n(r,s){return r?(s=s....
  function o (line 1) | function o(){}
  function h (line 1) | function h(e){for(var t,n,r=1;r<arguments.length;r++){t=arguments[r];for...
  function a (line 1) | function a(t,n,i){if(i||"function"==typeof n){i||(i=n,n=null),n=h({},a.d...

FILE: apps/barrel_rest/priv/swagger/lib/swagger-oauth.js
  function handleLogin (line 1) | function handleLogin(){var e=[],o=window.swaggerUiAuth.authSchemes||wind...
  function handleLogout (line 1) | function handleLogout(){for(key in window.swaggerUi.api.clientAuthorizat...
  function initOAuth (line 1) | function initOAuth(e){var o=e||{},i=[];return appName=o.appName||i.push(...
  function clientCredentialsFlow (line 1) | function clientCredentialsFlow(e,o,i){var n={client_id:clientId,client_s...

FILE: apps/barrel_rest/priv/swagger/swagger-ui.js
  function clippyCopiedCallback (line 858) | function clippyCopiedCallback() {
  function log (line 869) | function log(){
  function s (line 3169) | function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&re...
  function each (line 3169) | function each(obj,cb){if(obj)Object.keys(obj).forEach(function(key){cb(o...
  function has (line 3169) | function has(obj,key){return{}.hasOwnProperty.call(obj,key)}
  function sanitizeHtml (line 3169) | function sanitizeHtml(html,options,_recursing){var result="";function Fr...
  function init (line 3169) | function init(){var code="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrst...
  function toByteArray (line 3169) | function toByteArray(b64){var i,j,l,tmp,placeHolders,arr;var len=b64.len...
  function tripletToBase64 (line 3169) | function tripletToBase64(num){return lookup[num>>18&63]+lookup[num>>12&6...
  function encodeChunk (line 3169) | function encodeChunk(uint8,start,end){var tmp;var output=[];for(var i=st...
  function fromByteArray (line 3169) | function fromByteArray(uint8){var tmp;var len=uint8.length;var extraByte...
  function typedArraySupport (line 3169) | function typedArraySupport(){try{var arr=new Uint8Array(1);arr.__proto__...
  function kMaxLength (line 3169) | function kMaxLength(){return Buffer.TYPED_ARRAY_SUPPORT?2147483647:10737...
  function createBuffer (line 3169) | function createBuffer(that,length){if(kMaxLength()<length){throw new Ran...
  function Buffer (line 3169) | function Buffer(arg,encodingOrOffset,length){if(!Buffer.TYPED_ARRAY_SUPP...
  function from (line 3169) | function from(that,value,encodingOrOffset,length){if(typeof value==="num...
  function assertSize (line 3169) | function assertSize(size){if(typeof size!=="number"){throw new TypeError...
  function alloc (line 3169) | function alloc(that,size,fill,encoding){assertSize(size);if(size<=0){ret...
  function allocUnsafe (line 3169) | function allocUnsafe(that,size){assertSize(size);that=createBuffer(that,...
  function fromString (line 3169) | function fromString(that,string,encoding){if(typeof encoding!=="string"|...
  function fromArrayLike (line 3169) | function fromArrayLike(that,array){var length=array.length<0?0:checked(a...
  function fromArrayBuffer (line 3169) | function fromArrayBuffer(that,array,byteOffset,length){array.byteLength;...
  function fromObject (line 3169) | function fromObject(that,obj){if(Buffer.isBuffer(obj)){var len=checked(o...
  function checked (line 3169) | function checked(length){if(length>=kMaxLength()){throw new RangeError("...
  function SlowBuffer (line 3169) | function SlowBuffer(length){if(+length!=length){length=0}return Buffer.a...
  function byteLength (line 3169) | function byteLength(string,encoding){if(Buffer.isBuffer(string)){return ...
  function slowToString (line 3169) | function slowToString(encoding,start,end){var loweredCase=false;if(start...
  function swap (line 3169) | function swap(b,n,m){var i=b[n];b[n]=b[m];b[m]=i}
  function bidirectionalIndexOf (line 3169) | function bidirectionalIndexOf(buffer,val,byteOffset,encoding,dir){if(buf...
  function arrayIndexOf (line 3169) | function arrayIndexOf(arr,val,byteOffset,encoding,dir){var indexSize=1;v...
  function hexWrite (line 3169) | function hexWrite(buf,string,offset,length){offset=Number(offset)||0;var...
  function utf8Write (line 3169) | function utf8Write(buf,string,offset,length){return blitBuffer(utf8ToByt...
  function asciiWrite (line 3169) | function asciiWrite(buf,string,offset,length){return blitBuffer(asciiToB...
  function latin1Write (line 3169) | function latin1Write(buf,string,offset,length){return asciiWrite(buf,str...
  function base64Write (line 3169) | function base64Write(buf,string,offset,length){return blitBuffer(base64T...
  function ucs2Write (line 3169) | function ucs2Write(buf,string,offset,length){return blitBuffer(utf16leTo...
  function base64Slice (line 3169) | function base64Slice(buf,start,end){if(start===0&&end===buf.length){retu...
  function utf8Slice (line 3169) | function utf8Slice(buf,start,end){end=Math.min(buf.length,end);var res=[...
  function decodeCodePointsArray (line 3169) | function decodeCodePointsArray(codePoints){var len=codePoints.length;if(...
  function asciiSlice (line 3169) | function asciiSlice(buf,start,end){var ret="";end=Math.min(buf.length,en...
  function latin1Slice (line 3169) | function latin1Slice(buf,start,end){var ret="";end=Math.min(buf.length,e...
  function hexSlice (line 3169) | function hexSlice(buf,start,end){var len=buf.length;if(!start||start<0)s...
  function utf16leSlice (line 3169) | function utf16leSlice(buf,start,end){var bytes=buf.slice(start,end);var ...
  function checkOffset (line 3169) | function checkOffset(offset,ext,length){if(offset%1!==0||offset<0)throw ...
  function checkInt (line 3170) | function checkInt(buf,value,offset,ext,max,min){if(!Buffer.isBuffer(buf)...
  function objectWriteUInt16 (line 3170) | function objectWriteUInt16(buf,value,offset,littleEndian){if(value<0)val...
  function objectWriteUInt32 (line 3170) | function objectWriteUInt32(buf,value,offset,littleEndian){if(value<0)val...
  function checkIEEE754 (line 3170) | function checkIEEE754(buf,value,offset,ext,max,min){if(offset+ext>buf.le...
  function writeFloat (line 3170) | function writeFloat(buf,value,offset,littleEndian,noAssert){if(!noAssert...
  function writeDouble (line 3170) | function writeDouble(buf,value,offset,littleEndian,noAssert){if(!noAsser...
  function base64clean (line 3170) | function base64clean(str){str=stringtrim(str).replace(INVALID_BASE64_RE,...
  function stringtrim (line 3170) | function stringtrim(str){if(str.trim)return str.trim();return str.replac...
  function toHex (line 3170) | function toHex(n){if(n<16)return"0"+n.toString(16);return n.toString(16)}
  function utf8ToBytes (line 3170) | function utf8ToBytes(string,units){units=units||Infinity;var codePoint;v...
  function asciiToBytes (line 3170) | function asciiToBytes(str){var byteArray=[];for(var i=0;i<str.length;++i...
  function utf16leToBytes (line 3170) | function utf16leToBytes(str,units){var c,hi,lo;var byteArray=[];for(var ...
  function base64ToBytes (line 3170) | function base64ToBytes(str){return base64.toByteArray(base64clean(str))}
  function blitBuffer (line 3170) | function blitBuffer(src,dst,offset,length){for(var i=0;i<length;++i){if(...
  function isnan (line 3170) | function isnan(val){return val!==val}
  function isArray (line 3170) | function isArray(arg){if(Array.isArray){return Array.isArray(arg)}return...
  function isBoolean (line 3170) | function isBoolean(arg){return typeof arg==="boolean"}
  function isNull (line 3170) | function isNull(arg){return arg===null}
  function isNullOrUndefined (line 3170) | function isNullOrUndefined(arg){return arg==null}
  function isNumber (line 3170) | function isNumber(arg){return typeof arg==="number"}
  function isString (line 3170) | function isString(arg){return typeof arg==="string"}
  function isSymbol (line 3170) | function isSymbol(arg){return typeof arg==="symbol"}
  function isUndefined (line 3170) | function isUndefined(arg){return arg===void 0}
  function isRegExp (line 3170) | function isRegExp(re){return objectToString(re)==="[object RegExp]"}
  function isObject (line 3170) | function isObject(arg){return typeof arg==="object"&&arg!==null}
  function isDate (line 3170) | function isDate(d){return objectToString(d)==="[object Date]"}
  function isError (line 3170) | function isError(e){return objectToString(e)==="[object Error]"||e insta...
  function isFunction (line 3170) | function isFunction(arg){return typeof arg==="function"}
  function isPrimitive (line 3170) | function isPrimitive(arg){return arg===null||typeof arg==="boolean"||typ...
  function objectToString (line 3170) | function objectToString(o){return Object.prototype.toString.call(o)}
  function formatAttrs (line 3170) | function formatAttrs(attributes,opts){if(!attributes)return;var output="...
  function renderTag (line 3170) | function renderTag(elem,opts){if(elem.name==="svg")opts={decodeEntities:...
  function renderDirective (line 3170) | function renderDirective(elem){return"<"+elem.data+">"}
  function renderText (line 3170) | function renderText(elem,opts){var data=elem.data||"";if(opts.decodeEnti...
  function renderCdata (line 3170) | function renderCdata(elem){return"<![CDATA["+elem.children[0].data+"]]>"}
  function renderComment (line 3170) | function renderComment(elem){return"<!--"+elem.data+"-->"}
  function DomHandler (line 3170) | function DomHandler(callback,options,elementCB){if(typeof callback==="ob...
  method firstChild (line 3170) | get firstChild(){var children=this.children;return children&&children[0]...
  method lastChild (line 3170) | get lastChild(){var children=this.children;return children&&children[chi...
  method nodeType (line 3170) | get nodeType(){return nodeTypes[this.type]||nodeTypes.element}
  function getAttribCheck (line 3170) | function getAttribCheck(attrib,value){if(typeof value==="function"){retu...
  function combineFuncs (line 3170) | function combineFuncs(a,b){return function(elem){return a(elem)||b(elem)}}
  function filter (line 3170) | function filter(test,element,recurse,limit){if(!Array.isArray(element))e...
  function find (line 3170) | function find(test,elems,recurse,limit){var result=[],childs;for(var i=0...
  function findOneChild (line 3170) | function findOneChild(test,elems){for(var i=0,l=elems.length;i<l;i++){if...
  function findOne (line 3170) | function findOne(test,elems){var elem=null;for(var i=0,l=elems.length;i<...
  function existsOne (line 3170) | function existsOne(test,elems){for(var i=0,l=elems.length;i<l;i++){if(is...
  function findAll (line 3170) | function findAll(test,elems){var result=[];for(var i=0,j=elems.length;i<...
  function getInnerHTML (line 3170) | function getInnerHTML(elem,opts){return elem.children?elem.children.map(...
  function getText (line 3170) | function getText(elem){if(Array.isArray(elem))return elem.map(getText).j...
  function getStrictDecoder (line 3170) | function getStrictDecoder(map){var keys=Object.keys(map).join("|"),repla...
  function replacer (line 3170) | function replacer(str){if(str.substr(-1)!==";")str+=";";return replace(s...
  function sorter (line 3170) | function sorter(a,b){return a<b?1:-1}
  function getReplacer (line 3170) | function getReplacer(map){return function replace(str){if(str.charAt(1)=...
  function decodeCodePoint (line 3171) | function decodeCodePoint(codePoint){if(codePoint>=55296&&codePoint<=5734...
  function getInverseObj (line 3171) | function getInverseObj(obj){return Object.keys(obj).sort().reduce(functi...
  function getInverseReplacer (line 3171) | function getInverseReplacer(inverse){var single=[],multiple=[];Object.ke...
  function singleCharReplacer (line 3171) | function singleCharReplacer(c){return"&#x"+c.charCodeAt(0).toString(16)....
  function astralReplacer (line 3171) | function astralReplacer(c){var high=c.charCodeAt(0);var low=c.charCodeAt...
  function getInverse (line 3171) | function getInverse(inverse,re){function func(name){return inverse[name]...
  function escapeXML (line 3171) | function escapeXML(data){return data.replace(re_xmlChars,singleCharRepla...
  function EventEmitter (line 3171) | function EventEmitter(){this._events=this._events||{};this._maxListeners...
  function g (line 3171) | function g(){this.removeListener(type,g);if(!fired){fired=true;listener....
  function isFunction (line 3172) | function isFunction(arg){return typeof arg==="function"}
  function isNumber (line 3172) | function isNumber(arg){return typeof arg==="number"}
  function isObject (line 3172) | function isObject(arg){return typeof arg==="object"&&arg!==null}
  function isUndefined (line 3172) | function isUndefined(arg){return arg===void 0}
  function CollectingHandler (line 3172) | function CollectingHandler(cbs){this._cbs=cbs||{};this.events=[]}
  function FeedHandler (line 3172) | function FeedHandler(callback,options){this.init(callback,options)}
  function getElements (line 3172) | function getElements(what,where){return DomUtils.getElementsByTagName(wh...
  function getOneElement (line 3172) | function getOneElement(what,where){return DomUtils.getElementsByTagName(...
  function fetch (line 3172) | function fetch(what,where,recurse){return DomUtils.getText(DomUtils.getE...
  function addConditionally (line 3172) | function addConditionally(obj,prop,what,where,recurse){var tmp=fetch(wha...
  function Parser (line 3172) | function Parser(cbs,options){this._options=options||{};this._cbs=cbs||{}...
  function ProxyHandler (line 3172) | function ProxyHandler(cbs){this._cbs=cbs||{}}
  function Stream (line 3172) | function Stream(options){Parser.call(this,new Cbs(this),options)}
  function Cbs (line 3172) | function Cbs(scope){this.scope=scope}
  function whitespace (line 3172) | function whitespace(c){return c===" "||c==="\n"||c==="\t"||c==="\f"||c==...
  function characterState (line 3172) | function characterState(char,SUCCESS){return function(c){if(c===char)thi...
  function ifElseState (line 3172) | function ifElseState(upper,SUCCESS,FAILURE){var lower=upper.toLowerCase(...
  function consumeSpecialNameChar (line 3172) | function consumeSpecialNameChar(upper,NEXT_STATE){var lower=upper.toLowe...
  function Tokenizer (line 3172) | function Tokenizer(options,cbs){this._state=TEXT;this._buffer="";this._s...
  function Stream (line 3173) | function Stream(cbs,options){var parser=this._parser=new Parser(cbs,opti...
  function defineProp (line 3173) | function defineProp(name,value){delete module.exports[name];module.expor...
  method FeedHandler (line 3173) | get FeedHandler(){return defineProp("FeedHandler",require("./FeedHandler...
  method Stream (line 3173) | get Stream(){return defineProp("Stream",require("./Stream.js"))}
  method WritableStream (line 3173) | get WritableStream(){return defineProp("WritableStream",require("./Writa...
  method ProxyHandler (line 3173) | get ProxyHandler(){return defineProp("ProxyHandler",require("./ProxyHand...
  method DomUtils (line 3173) | get DomUtils(){return defineProp("DomUtils",require("domutils"))}
  method CollectingHandler (line 3173) | get CollectingHandler(){return defineProp("CollectingHandler",require("....
  method RssHandler (line 3173) | get RssHandler(){return defineProp("RssHandler",this.FeedHandler)}
  function isBuffer (line 3173) | function isBuffer(obj){return!!obj.constructor&&typeof obj.constructor.i...
  function isSlowBuffer (line 3173) | function isSlowBuffer(obj){return typeof obj.readFloatLE==="function"&&t...
  function nextTick (line 3173) | function nextTick(fn,arg1,arg2,arg3){if(typeof fn!=="function"){throw ne...
  function defaultSetTimout (line 3173) | function defaultSetTimout(){throw new Error("setTimeout has not been def...
  function defaultClearTimeout (line 3173) | function defaultClearTimeout(){throw new Error("clearTimeout has not bee...
  function runTimeout (line 3173) | function runTimeout(fun){if(cachedSetTimeout===setTimeout){return setTim...
  function runClearTimeout (line 3173) | function runClearTimeout(marker){if(cachedClearTimeout===clearTimeout){r...
  function cleanUpNextTick (line 3173) | function cleanUpNextTick(){if(!draining||!currentQueue){return}draining=...
  function drainQueue (line 3173) | function drainQueue(){if(draining){return}var timeout=runTimeout(cleanUp...
  function Item (line 3173) | function Item(fun,array){this.fun=fun;this.array=array}
  function noop (line 3173) | function noop(){}
  function Duplex (line 3173) | function Duplex(options){if(!(this instanceof Duplex))return new Duplex(...
  function onend (line 3173) | function onend(){if(this.allowHalfOpen||this._writableState.ended)return...
  function onEndNT (line 3173) | function onEndNT(self){self.end()}
  function forEach (line 3173) | function forEach(xs,f){for(var i=0,l=xs.length;i<l;i++){f(xs[i],i)}}
  function PassThrough (line 3173) | function PassThrough(options){if(!(this instanceof PassThrough))return n...
  function prependListener (line 3173) | function prependListener(emitter,event,fn){if(typeof emitter.prependList...
  function ReadableState (line 3173) | function ReadableState(options,stream){Duplex=Duplex||require("./_stream...
  function Readable (line 3173) | function Readable(options){Duplex=Duplex||require("./_stream_duplex");if...
  function readableAddChunk (line 3173) | function readableAddChunk(stream,state,chunk,encoding,addToFront){var er...
  function needMoreData (line 3173) | function needMoreData(state){return!state.ended&&(state.needReadable||st...
  function computeNewHighWaterMark (line 3173) | function computeNewHighWaterMark(n){if(n>=MAX_HWM){n=MAX_HWM}else{n--;n|...
  function howMuchToRead (line 3173) | function howMuchToRead(n,state){if(n<=0||state.length===0&&state.ended)r...
  function chunkInvalid (line 3173) | function chunkInvalid(state,chunk){var er=null;if(!Buffer.isBuffer(chunk...
  function onEofChunk (line 3173) | function onEofChunk(stream,state){if(state.ended)return;if(state.decoder...
  function emitReadable (line 3173) | function emitReadable(stream){var state=stream._readableState;state.need...
  function emitReadable_ (line 3173) | function emitReadable_(stream){debug("emit readable");stream.emit("reada...
  function maybeReadMore (line 3173) | function maybeReadMore(stream,state){if(!state.readingMore){state.readin...
  function maybeReadMore_ (line 3173) | function maybeReadMore_(stream,state){var len=state.length;while(!state....
  function onunpipe (line 3173) | function onunpipe(readable){debug("onunpipe");if(readable===src){cleanup...
  function onend (line 3173) | function onend(){debug("onend");dest.end()}
  function cleanup (line 3173) | function cleanup(){debug("cleanup");dest.removeListener("close",onclose)...
  function ondata (line 3173) | function ondata(chunk){debug("ondata");increasedAwaitDrain=false;var ret...
  function onerror (line 3173) | function onerror(er){debug("onerror",er);unpipe();dest.removeListener("e...
  function onclose (line 3173) | function onclose(){dest.removeListener("finish",onfinish);unpipe()}
  function onfinish (line 3173) | function onfinish(){debug("onfinish");dest.removeListener("close",onclos...
  function unpipe (line 3173) | function unpipe(){debug("unpipe");src.unpipe(dest)}
  function pipeOnDrain (line 3173) | function pipeOnDrain(src){return function(){var state=src._readableState...
  function nReadingNextTick (line 3173) | function nReadingNextTick(self){debug("readable nexttick read 0");self.r...
  function resume (line 3173) | function resume(stream,state){if(!state.resumeScheduled){state.resumeSch...
  function resume_ (line 3173) | function resume_(stream,state){if(!state.reading){debug("resume read 0")...
  function flow (line 3173) | function flow(stream){var state=stream._readableState;debug("flow",state...
  function fromList (line 3173) | function fromList(n,state){if(state.length===0)return null;var ret;if(st...
  function fromListPartial (line 3173) | function fromListPartial(n,list,hasStrings){var ret;if(n<list.head.data....
  function copyFromBufferString (line 3173) | function copyFromBufferString(n,list){var p=list.head;var c=1;var ret=p....
  function copyFromBuffer (line 3173) | function copyFromBuffer(n,list){var ret=bufferShim.allocUnsafe(n);var p=...
  function endReadable (line 3173) | function endReadable(stream){var state=stream._readableState;if(state.le...
  function endReadableNT (line 3173) | function endReadableNT(state,stream){if(!state.endEmitted&&state.length=...
  function forEach (line 3173) | function forEach(xs,f){for(var i=0,l=xs.length;i<l;i++){f(xs[i],i)}}
  function indexOf (line 3173) | function indexOf(xs,x){for(var i=0,l=xs.length;i<l;i++){if(xs[i]===x)ret...
  function TransformState (line 3173) | function TransformState(stream){this.afterTransform=function(er,data){re...
  function afterTransform (line 3173) | function afterTransform(stream,er,data){var ts=stream._transformState;ts...
  function Transform (line 3173) | function Transform(options){if(!(this instanceof Transform))return new T...
  function done (line 3173) | function done(stream,er){if(er)return stream.emit("error",er);var ws=str...
  function nop (line 3173) | function nop(){}
  function WriteReq (line 3173) | function WriteReq(chunk,encoding,cb){this.chunk=chunk;this.encoding=enco...
  function WritableState (line 3173) | function WritableState(options,stream){Duplex=Duplex||require("./_stream...
  function Writable (line 3173) | function Writable(options){Duplex=Duplex||require("./_stream_duplex");if...
  function writeAfterEnd (line 3173) | function writeAfterEnd(stream,cb){var er=new Error("write after end");st...
  function validChunk (line 3173) | function validChunk(stream,state,chunk,cb){var valid=true;var er=false;i...
  function decodeChunk (line 3174) | function decodeChunk(state,chunk,encoding){if(!state.objectMode&&state.d...
  function writeOrBuffer (line 3174) | function writeOrBuffer(stream,state,chunk,encoding,cb){chunk=decodeChunk...
  function doWrite (line 3174) | function doWrite(stream,state,writev,len,chunk,encoding,cb){state.writel...
  function onwriteError (line 3174) | function onwriteError(stream,state,sync,er,cb){--state.pendingcb;if(sync...
  function onwriteStateUpdate (line 3174) | function onwriteStateUpdate(state){state.writing=false;state.writecb=nul...
  function onwrite (line 3174) | function onwrite(stream,er){var state=stream._writableState;var sync=sta...
  function afterWrite (line 3174) | function afterWrite(stream,state,finished,cb){if(!finished)onwriteDrain(...
  function onwriteDrain (line 3174) | function onwriteDrain(stream,state){if(state.length===0&&state.needDrain...
  function clearBuffer (line 3174) | function clearBuffer(stream,state){state.bufferProcessing=true;var entry...
  function needFinish (line 3174) | function needFinish(state){return state.ending&&state.length===0&&state....
  function prefinish (line 3174) | function prefinish(stream,state){if(!state.prefinished){state.prefinishe...
  function finishMaybe (line 3174) | function finishMaybe(stream,state){var need=needFinish(state);if(need){i...
  function endWritable (line 3174) | function endWritable(stream,state,cb){state.ending=true;finishMaybe(stre...
  function CorkedRequest (line 3174) | function CorkedRequest(state){var _this=this;this.next=null;this.entry=n...
  function BufferList (line 3174) | function BufferList(){this.head=null;this.tail=null;this.length=0}
  function Stream (line 3174) | function Stream(){EE.call(this)}
  function ondata (line 3174) | function ondata(chunk){if(dest.writable){if(false===dest.write(chunk)&&s...
  function ondrain (line 3174) | function ondrain(){if(source.readable&&source.resume){source.resume()}}
  function onend (line 3174) | function onend(){if(didOnEnd)return;didOnEnd=true;dest.end()}
  function onclose (line 3174) | function onclose(){if(didOnEnd)return;didOnEnd=true;if(typeof dest.destr...
  function onerror (line 3174) | function onerror(er){cleanup();if(EE.listenerCount(this,"error")===0){th...
  function cleanup (line 3174) | function cleanup(){source.removeListener("data",ondata);dest.removeListe...
  function assertEncoding (line 3174) | function assertEncoding(encoding){if(encoding&&!isBufferEncoding(encodin...
  function passThroughWrite (line 3174) | function passThroughWrite(buffer){return buffer.toString(this.encoding)}
  function utf16DetectIncompleteChar (line 3174) | function utf16DetectIncompleteChar(buffer){this.charReceived=buffer.leng...
  function base64DetectIncompleteChar (line 3174) | function base64DetectIncompleteChar(buffer){this.charReceived=buffer.len...
  function deprecate (line 3174) | function deprecate(fn,msg){if(config("noDeprecation")){return fn}var war...
  function config (line 3174) | function config(name){try{if(!global.localStorage)return false}catch(_){...
  function extend (line 3174) | function extend(){var target={};for(var i=0;i<arguments.length;i++){var ...
  function s (line 3182) | function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&re...
  function splitUrl (line 5128) | function splitUrl(url) {
  function unsplitUrl (line 5149) | function unsplitUrl(url) {
  function joinUrl (line 5169) | function joinUrl(base, rel) {
  function addReference (line 5725) | function addReference(schema, name, skipRef) {
  function primitiveToHTML (line 5744) | function primitiveToHTML(schema) {
  function primitiveToOptionsHTML (line 5786) | function primitiveToOptionsHTML(schema, html) {
  function processModel (line 5881) | function processModel(schema, name) {
  function itemByPriority (line 7631) | function itemByPriority(col, itemPriority) {
  function drainQueue (line 7987) | function drainQueue() {
  function noop (line 8019) | function noop() {}
  function btoa (line 8045) | function btoa(str) {
  function Bar (line 8110) | function Bar () {}
  function kMaxLength (line 8124) | function kMaxLength () {
  function Buffer (line 8142) | function Buffer (arg) {
  function fromNumber (line 8166) | function fromNumber (that, length) {
  function fromString (line 8176) | function fromString (that, string, encoding) {
  function fromObject (line 8187) | function fromObject (that, object) {
  function fromBuffer (line 8210) | function fromBuffer (that, buffer) {
  function fromArray (line 8217) | function fromArray (that, array) {
  function fromTypedArray (line 8227) | function fromTypedArray (that, array) {
  function fromArrayBuffer (line 8239) | function fromArrayBuffer (that, array) {
  function fromArrayLike (line 8251) | function fromArrayLike (that, array) {
  function fromJsonObject (line 8262) | function fromJsonObject (that, object) {
  function allocate (line 8278) | function allocate (that, length) {
  function checked (line 8294) | function checked (length) {
  function SlowBuffer (line 8304) | function SlowBuffer (subject, encoding) {
  function byteLength (line 8388) | function byteLength (string, encoding) {
  function slowToString (line 8429) | function slowToString (encoding, start, end) {
  function arrayIndexOf (line 8526) | function arrayIndexOf (arr, val, byteOffset) {
  function hexWrite (line 8554) | function hexWrite (buf, string, offset, length) {
  function utf8Write (line 8581) | function utf8Write (buf, string, offset, length) {
  function asciiWrite (line 8585) | function asciiWrite (buf, string, offset, length) {
  function binaryWrite (line 8589) | function binaryWrite (buf, string, offset, length) {
  function base64Write (line 8593) | function base64Write (buf, string, offset, length) {
  function ucs2Write (line 8597) | function ucs2Write (buf, string, offset, length) {
  function base64Slice (line 8680) | function base64Slice (buf, start, end) {
  function utf8Slice (line 8688) | function utf8Slice (buf, start, end) {
  function decodeCodePointsArray (line 8766) | function decodeCodePointsArray (codePoints) {
  function asciiSlice (line 8784) | function asciiSlice (buf, start, end) {
  function binarySlice (line 8794) | function binarySlice (buf, start, end) {
  function hexSlice (line 8804) | function hexSlice (buf, start, end) {
  function utf16leSlice (line 8817) | function utf16leSlice (buf, start, end) {
  function checkOffset (line 8866) | function checkOffset (offset, ext, length) {
  function checkInt (line 9027) | function checkInt (buf, value, offset, ext, max, min) {
  function objectWriteUInt16 (line 9074) | function objectWriteUInt16 (buf, value, offset, littleEndian) {
  function objectWriteUInt32 (line 9108) | function objectWriteUInt32 (buf, value, offset, littleEndian) {
  function checkIEEE754 (line 9252) | function checkIEEE754 (buf, value, offset, ext, max, min) {
  function writeFloat (line 9258) | function writeFloat (buf, value, offset, littleEndian, noAssert) {
  function writeDouble (line 9274) | function writeDouble (buf, value, offset, littleEndian, noAssert) {
  function base64clean (line 9459) | function base64clean (str) {
  function stringtrim (line 9471) | function stringtrim (str) {
  function toHex (line 9476) | function toHex (n) {
  function utf8ToBytes (line 9481) | function utf8ToBytes (string, units) {
  function asciiToBytes (line 9561) | function asciiToBytes (str) {
  function utf16leToBytes (line 9570) | function utf16leToBytes (str, units) {
  function base64ToBytes (line 9586) | function base64ToBytes (str) {
  function blitBuffer (line 9590) | function blitBuffer (src, dst, offset, length) {
  function decode (line 9616) | function decode (elt) {
  function b64ToByteArray (line 9634) | function b64ToByteArray (b64) {
  function uint8ToBase64 (line 9680) | function uint8ToBase64 (uint8) {
  function CookieAccessInfo (line 9850) | function CookieAccessInfo(domain, path, secure, script) {
  function Cookie (line 9862) | function Cookie(cookiestr, request_domain, request_path) {
  function CookieJar (line 10002) | function CookieJar() {
  function deprecated (line 10125) | function deprecated(name) {
  function isNothing (line 10162) | function isNothing(subject) {
  function isObject (line 10167) | function isObject(subject) {
  function toArray (line 10172) | function toArray(sequence) {
  function extend (line 10180) | function extend(target, source) {
  function repeat (line 10196) | function repeat(string, count) {
  function isNegativeZero (line 10207) | function isNegativeZero(number) {
  function compileStyleMap (line 10278) | function compileStyleMap(schema, map) {
  function encodeHex (line 10306) | function encodeHex(character) {
  function State (line 10327) | function State(options) {
  function indentString (line 10349) | function indentString(string, spaces) {
  function generateNextLine (line 10375) | function generateNextLine(state, level) {
  function testImplicitResolving (line 10379) | function testImplicitResolving(state, str) {
  function isWhitespace (line 10394) | function isWhitespace(c) {
  function isPrintable (line 10402) | function isPrintable(c) {
  function isPlainSafe (line 10410) | function isPlainSafe(c) {
  function isPlainSafeFirst (line 10426) | function isPlainSafeFirst(c) {
  function chooseScalarStyle (line 10469) | function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineW...
  function writeScalar (line 10537) | function writeScalar(state, string, level, iskey) {
  function blockHeader (line 10586) | function blockHeader(string, indentPerLevel) {
  function dropEndingNewline (line 10598) | function dropEndingNewline(string) {
  function foldString (line 10604) | function foldString(string, width) {
  function foldLine (line 10641) | function foldLine(line, width) {
  function escapeString (line 10681) | function escapeString(string) {
  function writeFlowSequence (line 10697) | function writeFlowSequence(state, level, object) {
  function writeBlockSequence (line 10715) | function writeBlockSequence(state, level, object, compact) {
  function writeFlowMapping (line 10735) | function writeFlowMapping(state, level, object) {
  function writeBlockMapping (line 10775) | function writeBlockMapping(state, level, object, compact) {
  function detectType (line 10849) | function detectType(state, object, explicit) {
  function writeNode (line 10887) | function writeNode(state, level, object, block, compact, iskey) {
  function getDuplicateReferences (line 10961) | function getDuplicateReferences(object, state) {
  function inspectNode (line 10975) | function inspectNode(object, objects, duplicatesIndexes) {
  function dump (line 11004) | function dump(input, options) {
  function safeDump (line 11016) | function safeDump(input, options) {
  function YAMLException (line 11028) | function YAMLException(reason, mark) {
  function is_EOL (line 11101) | function is_EOL(c) {
  function is_WHITE_SPACE (line 11105) | function is_WHITE_SPACE(c) {
  function is_WS_OR_EOL (line 11109) | function is_WS_OR_EOL(c) {
  function is_FLOW_INDICATOR (line 11116) | function is_FLOW_INDICATOR(c) {
  function fromHexCode (line 11124) | function fromHexCode(c) {
  function escapedHexLen (line 11141) | function escapedHexLen(c) {
  function fromDecimalCode (line 11148) | function fromDecimalCode(c) {
  function simpleEscapeSequence (line 11156) | function simpleEscapeSequence(c) {
  function charFromCodepoint (line 11177) | function charFromCodepoint(c) {
  function State (line 11195) | function State(input, options) {
  function generateError (line 11229) | function generateError(state, message) {
  function throwError (line 11235) | function throwError(state, message) {
  function throwWarning (line 11239) | function throwWarning(state, message) {
  function captureSegment (line 11309) | function captureSegment(state, start, end, checkJson) {
  function mergeMappings (line 11333) | function mergeMappings(state, destination, source, overridableKeys) {
  function storeMappingPair (line 11352) | function storeMappingPair(state, _result, overridableKeys, keyTag, keyNo...
  function readLineBreak (line 11382) | function readLineBreak(state) {
  function skipSeparationSpace (line 11402) | function skipSeparationSpace(state, allowComments, checkIndent) {
  function testDocumentSeparator (line 11440) | function testDocumentSeparator(state) {
  function writeFoldedLines (line 11464) | function writeFoldedLines(state, count) {
  function readPlainScalar (line 11473) | function readPlainScalar(state, nodeIndent, withinFlowCollection) {
  function readSingleQuotedScalar (line 11582) | function readSingleQuotedScalar(state, nodeIndent) {
  function readDoubleQuotedScalar (line 11626) | function readDoubleQuotedScalar(state, nodeIndent) {
  function readFlowCollection (line 11705) | function readFlowCollection(state, nodeIndent) {
  function readBlockScalar (line 11810) | function readBlockScalar(state, nodeIndent) {
  function readBlockSequence (line 11953) | function readBlockSequence(state, nodeIndent) {
  function readBlockMapping (line 12015) | function readBlockMapping(state, nodeIndent, flowIndent) {
  function readTagProperty (line 12168) | function readTagProperty(state) {
  function readAnchorProperty (line 12262) | function readAnchorProperty(state) {
  function readAlias (line 12289) | function readAlias(state) {
  function composeNode (line 12319) | function composeNode(state, parentIndent, nodeContext, allowToSeek, allo...
  function readDocument (line 12475) | function readDocument(state) {
  function loadDocuments (line 12583) | function loadDocuments(input, options) {
  function loadAll (line 12619) | function loadAll(input, iterator, options) {
  function load (line 12628) | function load(input, options) {
  function safeLoadAll (line 12641) | function safeLoadAll(input, output, options) {
  function safeLoad (line 12646) | function safeLoad(input, options) {
  function Mark (line 12663) | function Mark(name, buffer, position, line, column) {
  function compileList (line 12744) | function compileList(schema, name, result) {
  function compileMap (line 12767) | function compileMap(/* lists... */) {
  function Schema (line 12782) | function Schema(definition) {
  function compileStyleAliases (line 12985) | function compileStyleAliases(map) {
  function Type (line 12999) | function Type(tag, options) {
  function resolveYamlBinary (line 13046) | function resolveYamlBinary(data) {
  function constructYamlBinary (line 13068) | function constructYamlBinary(data) {
  function representYamlBinary (line 13109) | function representYamlBinary(object /*, style*/) {
  function isBinary (line 13151) | function isBinary(object) {
  function resolveYamlBoolean (line 13168) | function resolveYamlBoolean(data) {
  function constructYamlBoolean (line 13177) | function constructYamlBoolean(data) {
  function isBoolean (line 13183) | function isBoolean(object) {
  function resolveYamlFloat (line 13213) | function resolveYamlFloat(data) {
  function constructYamlFloat (line 13221) | function constructYamlFloat(data) {
  function representYamlFloat (line 13260) | function representYamlFloat(object, style) {
  function isFloat (line 13293) | function isFloat(object) {
  function isHexCode (line 13313) | function isHexCode(c) {
  function isOctCode (line 13319) | function isOctCode(c) {
  function isDecCode (line 13323) | function isDecCode(c) {
  function resolveYamlInteger (line 13327) | function resolveYamlInteger(data) {
  function constructYamlInteger (line 13409) | function constructYamlInteger(data) {
  function isInteger (line 13452) | function isInteger(object) {
  function resolveJavascriptFunction (line 13500) | function resolveJavascriptFunction(data) {
  function constructJavascriptFunction (line 13520) | function constructJavascriptFunction(data) {
  function representJavascriptFunction (line 13547) | function representJavascriptFunction(object /*, style*/) {
  function isFunction (line 13551) | function isFunction(object) {
  function resolveJavascriptRegExp (line 13568) | function resolveJavascriptRegExp(data) {
  function constructJavascriptRegExp (line 13589) | function constructJavascriptRegExp(data) {
  function representJavascriptRegExp (line 13603) | function representJavascriptRegExp(object /*, style*/) {
  function isRegExp (line 13613) | function isRegExp(object) {
  function resolveJavascriptUndefined (line 13630) | function resolveJavascriptUndefined() {
  function constructJavascriptUndefined (line 13634) | function constructJavascriptUndefined() {
  function representJavascriptUndefined (line 13639) | function representJavascriptUndefined() {
  function isUndefined (line 13643) | function isUndefined(object) {
  function resolveYamlMerge (line 13670) | function resolveYamlMerge(data) {
  function resolveYamlNull (line 13684) | function resolveYamlNull(data) {
  function constructYamlNull (line 13693) | function constructYamlNull() {
  function isNull (line 13697) | function isNull(object) {
  function resolveYamlOmap (line 13723) | function resolveYamlOmap(data) {
  function constructYamlOmap (line 13751) | function constructYamlOmap(data) {
  function resolveYamlPairs (line 13768) | function resolveYamlPairs(data) {
  function constructYamlPairs (line 13791) | function constructYamlPairs(data) {
  function resolveYamlSet (line 13833) | function resolveYamlSet(data) {
  function constructYamlSet (line 13847) | function constructYamlSet(data) {
  function resolveYamlTimestamp (line 13889) | function resolveYamlTimestamp(data) {
  function constructYamlTimestamp (line 13896) | function constructYamlTimestamp(data) {
  function representYamlTimestamp (line 13945) | function representYamlTimestamp(object /*, style*/) {
  function indexOf (line 13992) | function indexOf(array, value, fromIndex) {
  function last (line 14026) | function last(array) {
  function lodash (line 14143) | function lodash(value) {
  function includes (line 14301) | function includes(collection, target, fromIndex, guard) {
  function map (line 14381) | function map(collection, iteratee, thisArg) {
  function restParam (line 14502) | function restParam(func, start) {
  function LazyWrapper (line 14546) | function LazyWrapper(value) {
  function LodashWrapper (line 14573) | function LodashWrapper(value, chainAll, actions) {
  function arrayCopy (line 14593) | function arrayCopy(source, array) {
  function arrayEach (line 14616) | function arrayEach(array, iteratee) {
  function arrayMap (line 14640) | function arrayMap(array, iteratee) {
  function arraySome (line 14664) | function arraySome(array, predicate) {
  function baseAssign (line 14691) | function baseAssign(object, source) {
  function baseCallback (line 14716) | function baseCallback(func, thisArg, argCount) {
  function baseClone (line 14812) | function baseClone(value, isDeep, customizer, key, object, stackA, stack...
  function baseCopy (line 14880) | function baseCopy(source, props, object) {
  function object (line 14907) | function object() {}
  function baseFind (line 14951) | function baseFind(collection, predicate, eachFunc, retKey) {
  function baseFindIndex (line 14975) | function baseFindIndex(array, predicate, fromRight) {
  function baseForIn (line 15021) | function baseForIn(object, iteratee) {
  function baseForOwn (line 15040) | function baseForOwn(object, iteratee) {
  function baseGet (line 15059) | function baseGet(object, path, pathKey) {
  function baseIndexOf (line 15090) | function baseIndexOf(array, value, fromIndex) {
  function baseIsEqual (line 15125) | function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) {
  function baseIsEqualDeep (line 15177) | function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, ...
  function baseIsMatch (line 15256) | function baseIsMatch(object, matchData, customizer) {
  function baseLodash (line 15302) | function baseLodash() {
  function baseMap (line 15321) | function baseMap(collection, iteratee) {
  function baseMatches (line 15345) | function baseMatches(source) {
  function baseMatchesProperty (line 15385) | function baseMatchesProperty(path, srcValue) {
  function baseProperty (line 15423) | function baseProperty(key) {
  function basePropertyDeep (line 15442) | function basePropertyDeep(path) {
  function baseSlice (line 15481) | function baseSlice(array, start, end) {
  function baseToString (line 15514) | function baseToString(value) {
  function baseValues (line 15531) | function baseValues(object, props) {
  function binaryIndex (line 15563) | function binaryIndex(array, value, retHighest) {
  function binaryIndexBy (line 15607) | function binaryIndexBy(array, value, iteratee, retHighest) {
  function bindCallback (line 15657) | function bindCallback(func, thisArg, argCount) {
  function bufferClone (line 15698) | function bufferClone(buffer) {
  function composeArgs (line 15724) | function composeArgs(args, partials, holders) {
  function composeArgsRight (line 15760) | function composeArgsRight(args, partials, holders) {
  function createBaseEach (line 15797) | function createBaseEach(eachFunc, fromRight) {
  function createBaseFor (line 15827) | function createBaseFor(fromRight) {
  function createBindWrapper (line 15859) | function createBindWrapper(func, thisArg) {
  function createCtorWrapper (line 15885) | function createCtorWrapper(Ctor) {
  function createFind (line 15926) | function createFind(eachFunc, fromRight) {
  function createForEach (line 15951) | function createForEach(arrayFunc, eachFunc) {
  function createHybridWrapper (line 16002) | function createHybridWrapper(func, bitmask, thisArg, partials, holders, ...
  function createPartialWrapper (line 16096) | function createPartialWrapper(func, bitmask, thisArg, partials) {
  function createWrapper (line 16171) | function createWrapper(func, bitmask, thisArg, partials, holders, argPos...
  function equalArrays (line 16230) | function equalArrays(array, other, equalFunc, customizer, isLoose, stack...
  function equalByTag (line 16288) | function equalByTag(object, other, tag) {
  function equalObjects (line 16339) | function equalObjects(object, other, equalFunc, customizer, isLoose, sta...
  function getFuncName (line 16412) | function getFuncName(func) {
  function getMatchData (line 16457) | function getMatchData(object) {
  function getNative (line 16480) | function getNative(object, key) {
  function indexOfNaN (line 16497) | function indexOfNaN(array, fromIndex, fromRight) {
  function initCloneArray (line 16526) | function initCloneArray(array) {
  function initCloneByTag (line 16592) | function initCloneByTag(object, tag, isDeep) {
  function initCloneObject (line 16635) | function initCloneObject(object) {
  function isArrayLike (line 16656) | function isArrayLike(value) {
  function isIndex (line 16703) | function isIndex(value, length) {
  function isIterateeCall (line 16725) | function isIterateeCall(value, index, object) {
  function isKey (line 16757) | function isKey(value, object) {
  function isLaziable (line 16784) | function isLaziable(func) {
  function isLength (line 16816) | function isLength(value) {
  function isObjectLike (line 16830) | function isObjectLike(value) {
  function isStrictComparable (line 16847) | function isStrictComparable(value) {
  function mergeData (line 16887) | function mergeData(data, source) {
  function reorder (line 16981) | function reorder(array, indexes) {
  function replaceHolders (line 17008) | function replaceHolders(array, placeholder) {
  function shimKeys (line 17090) | function shimKeys(object) {
  function toObject (line 17124) | function toObject(value) {
  function toPath (line 17157) | function toPath(value) {
  function wrapperClone (line 17182) | function wrapperClone(wrapper) {
  function cloneDeep (line 17239) | function cloneDeep(value, customizer, thisArg) {
  function isArguments (line 17276) | function isArguments(value) {
  function isEmpty (line 17361) | function isEmpty(value) {
  function isFunction (line 17405) | function isFunction(value) {
  function isNative (line 17453) | function isNative(value) {
  function isObject (line 17486) | function isObject(value) {
  function isPlainObject (line 17547) | function isPlainObject(value) {
  function isString (line 17608) | function isString(value) {
  function isTypedArray (line 17684) | function isTypedArray(value) {
  function isUndefined (line 17707) | function isUndefined(value) {
  function keysIn (line 17841) | function keysIn(object) {
  function pairs (line 17917) | function pairs(object) {
  function values (line 17963) | function values(object) {
  function identity (line 18083) | function identity(value) {
  function noop (line 18104) | function noop() {
  function property (line 18137) | function property(path) {
  function flush (line 18255) | function flush() {
  function runSingle (line 18279) | function runSingle(task, domain) {
  function uncurryThis (line 18405) | function uncurryThis(f) {
  function Type (line 18469) | function Type() { }
  function isObject (line 18488) | function isObject(value) {
  function isStopIteration (line 18495) | function isStopIteration(exception) {
  function makeStackTraceLong (line 18517) | function makeStackTraceLong(error, promise) {
  function filterStackString (line 18540) | function filterStackString(stackString) {
  function isNodeFrame (line 18553) | function isNodeFrame(stackLine) {
  function getFileNameAndLineNumber (line 18558) | function getFileNameAndLineNumber(stackLine) {
  function isInternalFrame (line 18579) | function isInternalFrame(stackLine) {
  function captureLine (line 18596) | function captureLine() {
  function deprecate (line 18616) | function deprecate(callback, name, alternative) {
  function Q (line 18635) | function Q(value) {
  function defer (line 18679) | function defer() {
  function promise (line 18820) | function promise(resolver) {
  function race (line 18883) | function race(answerPs) {
  function Promise (line 18912) | function Promise(descriptor, fallback, inspect) {
  function _fulfilled (line 18976) | function _fulfilled(value) {
  function _rejected (line 18984) | function _rejected(exception) {
  function _progressed (line 18996) | function _progressed(value) {
  function when (line 19082) | function when(value, fulfilled, rejected, progressed) {
  function nearer (line 19114) | function nearer(value) {
  function isPromise (line 19129) | function isPromise(object) {
  function isPromiseAlike (line 19134) | function isPromiseAlike(object) {
  function isPending (line 19143) | function isPending(object) {
  function isFulfilled (line 19156) | function isFulfilled(object) {
  function isRejected (line 19168) | function isRejected(object) {
  function resetUnhandledRejections (line 19187) | function resetUnhandledRejections() {
  function trackRejection (line 19196) | function trackRejection(promise, reason) {
  function untrackRejection (line 19217) | function untrackRejection(promise) {
  function reject (line 19259) | function reject(reason) {
  function fulfill (line 19285) | function fulfill(value) {
  function coerce (line 19324) | function coerce(promise) {
  function master (line 19346) | function master(object) {
  function spread (line 19367) | function spread(value, fulfilled, rejected) {
  function async (line 19404) | function async(makeGenerator) {
  function spawn (line 19461) | function spawn(makeGenerator) {
  function _return (line 19491) | function _return(value) {
  function promised (line 19511) | function promised(callback) {
  function dispatch (line 19527) | function dispatch(object, op, args) {
  function all (line 19705) | function all(promises) {
  function any (line 19753) | function any(promises) {
  function allResolved (line 19803) | function allResolved(promises) {
  function allSettled (line 19822) | function allSettled(promises) {
  function regardless (line 19837) | function regardless() {
  function progress (line 19873) | function progress(object, progressed) {
  function bound (line 20085) | function bound() {
  function nodeify (line 20163) | function nodeify(object, nodeback) {
  function noop (line 20219) | function noop(){}
  function serialize (line 20265) | function serialize(obj) {
  function pushEncodedKeyValuePair (line 20283) | function pushEncodedKeyValuePair(pairs, key, val) {
  function parseString (line 20316) | function parseString(str) {
  function parseHeader (line 20395) | function parseHeader(str) {
  function isJSON (line 20424) | function isJSON(mime) {
  function type (line 20436) | function type(str){
  function params (line 20448) | function params(str){
  function Response (line 20505) | function Response(req, options) {
  function Request (line 20668) | function Request(method, url) {
  function del (line 21111) | function del(url, fn){
  function isObject (line 21183) | function isObject(obj) {
  function request (line 21556) | function request(RequestConstructor, method, url) {
  function Emitter (line 21588) | function Emitter(obj) {
  function mixin (line 21600) | function mixin(obj) {
  function on (line 21635) | function on() {
  function warn (line 22020) | function warn(message) {
  function getTokenName (line 22531) | function getTokenName(dets) {
  function addReference (line 24347) | function addReference(schema, name, skipRef) {
  function primitiveToHTML (line 24366) | function primitiveToHTML(schema) {
  function primitiveToOptionsHTML (line 24408) | function primitiveToOptionsHTML(schema, html) {
  function processModel (line 24511) | function processModel(schema, name) {
  function createObjectXML (line 24987) | function createObjectXML (descriptor) {
  function getInfiniteLoopMessage (line 25033) | function getInfiniteLoopMessage (name, loopTo) {
  function getErrorMessage (line 25037) | function getErrorMessage (details) {
  function createSchemaXML (line 25042) | function createSchemaXML (name, definition, models, config) {
  function Descriptor (line 25076) | function Descriptor (name, type, definition, models, config) {
  function getDescriptorByRef (line 25089) | function getDescriptorByRef($ref, name, models, config) {
  function getDescriptor (line 25115) | function getDescriptor (name, definition, models, config){
  function createXMLSample (line 25128) | function createXMLSample (name, definition, models, isParam) {
Condensed preview — 104 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,308K chars).
[
  {
    "path": ".codeclimate.yml",
    "chars": 50,
    "preview": "exclude_paths:\n- \"apps/barrel_http/priv/swagger/\"\n"
  },
  {
    "path": ".dir-locals.el",
    "chars": 122,
    "preview": ";; This file will set emacs to use tabwidth of 2 for this project\n;;\n((nil . ((indent-tabs-mode . t)\n\t (tab-width . 2)))"
  },
  {
    "path": ".eqc_ci",
    "chars": 35,
    "preview": "%-*-Erlang-*-\n\n{build, \"make eqc\"}."
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "chars": 393,
    "preview": "(REPLACE ALL UPPERCASE EXPRESSIONS AND DELETE THIS LINE TO SUBMIT)\n\n#### Description :octocat:\n\n(DESCRIPTION OF THE PROB"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 220,
    "preview": "Thank you for contributing to Barrel!\n\nBefore you submit this pull request, please ensure it is against the develop bran"
  },
  {
    "path": ".gitignore",
    "chars": 259,
    "preview": ".rebar3\n_*\n.eunit\n*.o\n*.beam\n*.plt\n*.swp\n*.swo\n.idea\n.erlang.cookie\nebin\nlog\nerl_crash.dump\n.rebar\nlog\nlogs\n_build\ndocs\n"
  },
  {
    "path": ".gitlab/issue_templates/Bug.md",
    "chars": 239,
    "preview": "\n\nWe’re closing our issue tracker on Gitlab so we can focus on the [Github.com](https://github.com/barrel-db/barrel-plat"
  },
  {
    "path": "EQC_CI_LICENCE.txt",
    "chars": 1569,
    "preview": "This file is an agreement between Quviq AB (\"Quviq\"), Sven Hultins\nGata 9, Gothenburg, Sweden, and the committers to the"
  },
  {
    "path": "HowToRunQuickCheck.md",
    "chars": 681,
    "preview": "# How to run QuickCheck\n\nIn order to run QuickCheck you will need a license and to install QuickCheck.\n\n## To Install Qu"
  },
  {
    "path": "LICENSE",
    "chars": 11357,
    "preview": "\n                                 Apache License\n                           Version 2.0, January 2004\n                  "
  },
  {
    "path": "Makefile",
    "chars": 1664,
    "preview": "BASEDIR = $(shell pwd)\nSUPPORTDIR = $(BASEDIR)/support\nREBAR ?= $(SUPPORTDIR)/rebar3\n\nOTP_VERSION?=19.3\nBUILD_NAME?=dirt"
  },
  {
    "path": "README.md",
    "chars": 2934,
    "preview": "\n<img src=\"https://raw.githubusercontent.com/barrel-db/media/master/banner/barrel-banner-groupfb.png\">\n\n<p align=\"center"
  },
  {
    "path": "apps/barrel_ctl/src/barrel_ctl.app.src",
    "chars": 246,
    "preview": "{application, barrel_ctl,\n [{description, \"An OTP library\"},\n  {vsn, \"0.1.0\"},\n  {registered, []},\n  {applications,\n   ["
  },
  {
    "path": "apps/barrel_ctl/src/barrel_ctl.erl",
    "chars": 976,
    "preview": "-module(barrel_ctl).\n\n%% API exports\n-export([\n  new_snapshot/1,\n  restore_from_snapshot/1\n]).\n\n\nnew_snapshot([DbName, P"
  },
  {
    "path": "apps/barrel_httpc/.gitignore",
    "chars": 128,
    "preview": ".rebar3\n_*\n.eunit\n*.o\n*.beam\n*.plt\n*.swp\n*.swo\n.erlang.cookie\nebin\nlog\nerl_crash.dump\n.rebar\nlogs\n_build\n.idea\nrebar3.cr"
  },
  {
    "path": "apps/barrel_httpc/LICENSE",
    "chars": 1474,
    "preview": "Copyright (c) 2017, Benoit Chesneau <bchesneau@gmail.com>.\nAll rights reserved.\n\nRedistribution and use in source and bi"
  },
  {
    "path": "apps/barrel_httpc/README.md",
    "chars": 74,
    "preview": "barrel_httpc\n=====\n\nAn OTP application\n\nBuild\n-----\n\n    $ rebar3 compile\n"
  },
  {
    "path": "apps/barrel_httpc/rebar.config",
    "chars": 40,
    "preview": "{erl_opts, [debug_info]}.\n{deps, [\n\n\n]}."
  },
  {
    "path": "apps/barrel_httpc/src/barrel_httpc.app.src",
    "chars": 324,
    "preview": "{application, barrel_httpc,\n [{description, \"An OTP application\"},\n  {vsn, \"0.1.0\"},\n  {registered, []},\n  {mod, { barre"
  },
  {
    "path": "apps/barrel_httpc/src/barrel_httpc.erl",
    "chars": 31578,
    "preview": "%%%-------------------------------------------------------------------\n%%% @author benoitc\n%%% @copyright (C) 2017, <COM"
  },
  {
    "path": "apps/barrel_httpc/src/barrel_httpc_app.erl",
    "chars": 770,
    "preview": "%%%-------------------------------------------------------------------\n%% @doc barrel_httpc public API\n%% @end\n%%%------"
  },
  {
    "path": "apps/barrel_httpc/src/barrel_httpc_attachments.erl",
    "chars": 6909,
    "preview": "%% Copyright 2016, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_httpc/src/barrel_httpc_changes.erl",
    "chars": 13113,
    "preview": "%% Copyright 2017, Benoit Chesneau\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n%% "
  },
  {
    "path": "apps/barrel_httpc/src/barrel_httpc_fold.erl",
    "chars": 6425,
    "preview": "%%%-------------------------------------------------------------------\n%%% @author benoitc\n%%% @copyright (C) 2017, <COM"
  },
  {
    "path": "apps/barrel_httpc/src/barrel_httpc_lib.erl",
    "chars": 1405,
    "preview": "%%%-------------------------------------------------------------------\n%%% @author benoitc\n%%% @copyright (C) 2017, <COM"
  },
  {
    "path": "apps/barrel_httpc/src/barrel_httpc_sup.erl",
    "chars": 1020,
    "preview": "%%%-------------------------------------------------------------------\n%% @doc barrel top level supervisor.\n%% @end\n%%%-"
  },
  {
    "path": "apps/barrel_httpc/src/barrel_jsonpointer.erl",
    "chars": 3097,
    "preview": "%% Copyright 2016-2017, Benoit Chesneau\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may no"
  },
  {
    "path": "apps/barrel_httpc/test/barrel_httpc_attachments_SUITE.erl",
    "chars": 7560,
    "preview": "%% Copyright 2016, Benoit Chesneau\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n%% "
  },
  {
    "path": "apps/barrel_httpc/test/barrel_httpc_changes_test_SUITE.erl",
    "chars": 9832,
    "preview": "%% Copyright 2017, Benoit Chesneau\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n%% "
  },
  {
    "path": "apps/barrel_httpc/test/barrel_httpc_test_SUITE.erl",
    "chars": 21673,
    "preview": "%% Copyright 2017, Benoit Chesneau\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n%% "
  },
  {
    "path": "apps/barrel_rest/.gitignore",
    "chars": 128,
    "preview": ".rebar3\n_*\n.eunit\n*.o\n*.beam\n*.plt\n*.swp\n*.swo\n.erlang.cookie\nebin\nlog\nerl_crash.dump\n.rebar\nlogs\n_build\n.idea\nrebar3.cr"
  },
  {
    "path": "apps/barrel_rest/LICENSE",
    "chars": 1474,
    "preview": "Copyright (c) 2017, Benoit Chesneau <bchesneau@gmail.com>.\nAll rights reserved.\n\nRedistribution and use in source and bi"
  },
  {
    "path": "apps/barrel_rest/README.md",
    "chars": 73,
    "preview": "barrel_rest\n=====\n\nAn OTP application\n\nBuild\n-----\n\n    $ rebar3 compile\n"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/css/print.css",
    "chars": 41666,
    "preview": ".swagger-section pre code{display:block;padding:.5em;background:#f0f0f0}.swagger-section pre .clojure .built_in,.swagger"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/css/reset.css",
    "chars": 773,
    "preview": "a,abbr,acronym,address,applet,article,aside,audio,b,big,blockquote,body,canvas,caption,center,cite,code,dd,del,details,d"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/css/screen.css",
    "chars": 43644,
    "preview": ".swagger-section pre code{display:block;padding:.5em;background:#f0f0f0}.swagger-section pre .clojure .built_in,.swagger"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/css/style.css",
    "chars": 3488,
    "preview": ".swagger-section #header a#logo{font-size:1.5em;font-weight:700;text-decoration:none;padding:20px 0 20px 40px}#text-head"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/css/typography.css",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "apps/barrel_rest/priv/swagger/index.html",
    "chars": 4314,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"UTF-8\">\n  <meta http-equiv=\"x-ua-compatible\" content=\"IE=edge\">\n  <title>"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lang/ca.js",
    "chars": 2381,
    "preview": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"Advertència: Ob"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lang/el.js",
    "chars": 2565,
    "preview": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"Προειδοποίηση: "
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lang/en.js",
    "chars": 2342,
    "preview": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"Warning: Deprec"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lang/es.js",
    "chars": 2448,
    "preview": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"Advertencia: Ob"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lang/fr.js",
    "chars": 2462,
    "preview": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"Avertissement :"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lang/geo.js",
    "chars": 2378,
    "preview": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"ყურადღება: აღარ"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lang/it.js",
    "chars": 2430,
    "preview": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"Attenzione: Dep"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lang/ja.js",
    "chars": 1965,
    "preview": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"警告: 廃止予定\",\n    "
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lang/ko-kr.js",
    "chars": 1800,
    "preview": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"경고:폐기예정됨\",\n    "
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lang/pl.js",
    "chars": 2253,
    "preview": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"Uwaga: Wycofane"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lang/pt.js",
    "chars": 2279,
    "preview": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"Aviso: Deprecia"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lang/ru.js",
    "chars": 2361,
    "preview": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"Предупреждение:"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lang/tr.js",
    "chars": 2200,
    "preview": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"Uyarı: Deprecat"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lang/translator.js",
    "chars": 1421,
    "preview": "'use strict';\n\n/**\n * Translator for documentation pages.\n *\n * To enable translation you should include one of language"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lang/zh-cn.js",
    "chars": 1795,
    "preview": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"警告:已过时\",\n    \"I"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lib/backbone-min.js",
    "chars": 19371,
    "preview": "!function(t,e){if(\"function\"==typeof define&&define.amd)define([\"underscore\",\"jquery\",\"exports\"],function(i,n,s){t.Backb"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lib/es5-shim.js",
    "chars": 22681,
    "preview": "!function(t,e){\"use strict\";\"function\"==typeof define&&define.amd?define(e):\"object\"==typeof exports?module.exports=e():"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lib/handlebars-4.0.5.js",
    "chars": 71504,
    "preview": "!function(t,e){\"object\"==typeof exports&&\"object\"==typeof module?module.exports=e():\"function\"==typeof define&&define.am"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lib/highlight.9.1.0.pack.js",
    "chars": 10962,
    "preview": "!function(e){\"undefined\"!=typeof exports?e(exports):(self.hljs=e({}),\"function\"==typeof define&&define.amd&&define(\"hljs"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lib/highlight.9.1.0.pack_extended.js",
    "chars": 310,
    "preview": "\"use strict\";!function(){var h,l;h=hljs.configure,hljs.configure=function(l){var i=l.highlightSizeThreshold;hljs.highlig"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lib/marked.js",
    "chars": 15712,
    "preview": "(function(){function e(e){this.tokens=[],this.tokens.links={},this.options=e||a.defaults,this.rules=p.normal,this.option"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lib/object-assign-pollyfill.js",
    "chars": 349,
    "preview": "\"function\"!=typeof Object.assign&&!function(){Object.assign=function(n){\"use strict\";if(void 0===n||null===n)throw new T"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/lib/swagger-oauth.js",
    "chars": 7042,
    "preview": "function handleLogin(){var e=[],o=window.swaggerUiAuth.authSchemes||window.swaggerUiAuth.securityDefinitions;if(o){var i"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/o2c.html",
    "chars": 479,
    "preview": "<script>\nvar qp = null;\nif(/code|token|error/.test(window.location.hash)) {\n  qp = location.hash.substring(1);\n}\nelse {\n"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/swagger-ui.js",
    "chars": 2704018,
    "preview": "/**\n * swagger-ui - Swagger UI is a dependency-free collection of HTML, JavaScript, and CSS assets that dynamically gene"
  },
  {
    "path": "apps/barrel_rest/priv/swagger/swagger.yaml",
    "chars": 14671,
    "preview": "swagger: '2.0'\ninfo:\n  version: 1.0.0\n  title: Barrel-db API\n  description: A document oriented reactive platform.\n  con"
  },
  {
    "path": "apps/barrel_rest/rebar.config",
    "chars": 138,
    "preview": "{erl_opts, [debug_info]}.\n{deps, [\n  %% client and http deps\n  {cowboy, {git, \"https://github.com/ninenines/cowboy.git\","
  },
  {
    "path": "apps/barrel_rest/src/barrel_http_count.erl",
    "chars": 2355,
    "preview": "%% Copyright 2017, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_rest/src/barrel_http_lib.erl",
    "chars": 1892,
    "preview": "%% Copyright 2016, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_rest/src/barrel_http_redirect.erl",
    "chars": 844,
    "preview": "%% Copyright 2017, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_rest/src/barrel_http_reply.erl",
    "chars": 2152,
    "preview": "%% Copyright 2016, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_rest/src/barrel_http_rest_db.erl",
    "chars": 2329,
    "preview": "%% Copyright 2016, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_rest/src/barrel_http_rest_dbs.erl",
    "chars": 2167,
    "preview": "%% Copyright 2016, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_rest/src/barrel_http_rest_docs.erl",
    "chars": 5010,
    "preview": "%% Copyright 2017, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_rest/src/barrel_http_rest_docs.hrl",
    "chars": 1051,
    "preview": "%% Copyright 2017, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_rest/src/barrel_http_rest_docs_changes.erl",
    "chars": 6228,
    "preview": "%% Copyright 2017, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_rest/src/barrel_http_rest_docs_id.erl",
    "chars": 7977,
    "preview": "%% Copyright 2016, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_rest/src/barrel_http_rest_docs_list.erl",
    "chars": 5597,
    "preview": "%% Copyright 2016, Bernard Notarianni\n%% Copyright 2017 Benoit Chesneau\n%%\n%% Licensed under the Apache License, Version"
  },
  {
    "path": "apps/barrel_rest/src/barrel_http_rest_replicate.erl",
    "chars": 7617,
    "preview": "%% Copyright 2016, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_rest/src/barrel_http_rest_revsdiff.erl",
    "chars": 1399,
    "preview": "%% Copyright 2016, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_rest/src/barrel_http_rest_root.erl",
    "chars": 997,
    "preview": "%% Copyright 2016, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_rest/src/barrel_http_rest_system.erl",
    "chars": 2885,
    "preview": "%% Copyright 2016, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_rest/src/barrel_http_rest_walk.erl",
    "chars": 5514,
    "preview": "%% Copyright 2016, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_rest/src/barrel_rest.app.src",
    "chars": 421,
    "preview": "{application, barrel_rest,\n [{description, \"An OTP application\"},\n  {vsn, \"0.1.0\"},\n  {registered, []},\n  {mod, { barrel"
  },
  {
    "path": "apps/barrel_rest/src/barrel_rest_app.erl",
    "chars": 767,
    "preview": "%%%-------------------------------------------------------------------\n%% @doc barrel_rest public API\n%% @end\n%%%-------"
  },
  {
    "path": "apps/barrel_rest/src/barrel_rest_ids.erl",
    "chars": 935,
    "preview": "%%%-------------------------------------------------------------------\n%%% @author benoitc\n%%% @copyright (C) 2017, <COM"
  },
  {
    "path": "apps/barrel_rest/src/barrel_rest_sup.erl",
    "chars": 3719,
    "preview": "%% Copyright 2016, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_rest/test/barrel_rest_all_docs_SUITE.erl",
    "chars": 3088,
    "preview": "%% Copyright 2016, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_rest/test/barrel_rest_changes_SUITE.erl",
    "chars": 6403,
    "preview": "%% Copyright 2017, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_rest/test/barrel_rest_dbs_SUITE.erl",
    "chars": 2500,
    "preview": "%% Copyright 2016, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_rest/test/barrel_rest_doc_SUITE.erl",
    "chars": 11791,
    "preview": "%% Copyright 2016, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_rest/test/barrel_rest_ids_SUITE.erl",
    "chars": 1238,
    "preview": "%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n%% use this file except in compliance wit"
  },
  {
    "path": "apps/barrel_rest/test/barrel_rest_replicate_SUITE.erl",
    "chars": 7960,
    "preview": "%% Copyright 2016, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_rest/test/barrel_rest_system_SUITE.erl",
    "chars": 1632,
    "preview": "%% Copyright 2016, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "apps/barrel_rest/test/test_lib.erl",
    "chars": 2300,
    "preview": "%% Copyright 2016, Bernard Notarianni\n%%\n%% Licensed under the Apache License, Version 2.0 (the \"License\"); you may not\n"
  },
  {
    "path": "bin/barrel_ctl.sh",
    "chars": 614,
    "preview": "#!/bin/sh\n\n# /bin/sh on Solaris is not a POSIX compatible shell, but /usr/bin/ksh is.\nif [ `uname -s` = 'SunOS' -a \"${PO"
  },
  {
    "path": "config/sys.config",
    "chars": 192,
    "preview": "%% -*- erlang -*-\n[\n\n  {barrel_rest, [\n    {listen_port, 7080},\n    {access_log, true}\n  ]},\n\n  {barrel, [\n    %%{data_d"
  },
  {
    "path": "config/vm.args",
    "chars": 1118,
    "preview": "## Name of the node\n-name barrel@127.0.0.1\n\n## Cookie for distributed erlang\n-setcookie barrel\n\n## Force the erlang VM t"
  },
  {
    "path": "rebar.config",
    "chars": 3111,
    "preview": "%% -*- mode: erlang;erlang-indent-level: 2;indent-tabs-mode: nil -*-\n%% ex: ts=4 sw=4 ft=erlang et\n\n%% == Erlang Compile"
  },
  {
    "path": "support/import.sh",
    "chars": 402,
    "preview": "#!/usr/bin/env sh\n\nPROJECT=`pwd`\nLIB_DIR=$PROJECT/_build/import/lib\nREBAR=$PROJECT/support/rebar3\n\nrm  -rf $PROJECT/lib "
  },
  {
    "path": "support/qa/README.md",
    "chars": 4116,
    "preview": "# Quality Assurance helpers\n\nThis directory contains some helper function to be run mannualy for Quality\nAssurance plan."
  },
  {
    "path": "support/qa/helpchange.erl",
    "chars": 601,
    "preview": "-module(helpchange).\n\n-export([ start/0\n        , post/1\n        ]).\n\nstart() ->\n  {ok, Conn} = barrel_httpc:connect(<<\""
  },
  {
    "path": "support/qa/helpreplicate.erl",
    "chars": 766,
    "preview": "-module(helpreplicate).\n\n-export([ start/0\n        , post_on_source/1\n        , target_docs/0\n        ]).\n\nstart() ->\n  "
  },
  {
    "path": "support/remove_deps.escript",
    "chars": 341,
    "preview": "#!/usr/bin/env escript\n%% -*- erlang -*-\nmain([File]) ->\n  {ok, Config0} = file:consult(File),\n  Config1 = proplists:del"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the barrel-db/barrel-platform GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 104 files (3.1 MB), approximately 813.2k tokens, and a symbol index with 671 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!