File Coverage

blib/lib/Arango/DB/API.pm
Criterion Covered Total %
statement 30 59 50.8
branch 0 20 0.0
condition 0 8 0.0
subroutine 10 12 83.3
pod n/a
total 40 99 40.4


line stmt bran cond sub pod time code
1             # ABSTRACT: Internal module with the API specification
2             package Arango::DB::API;
3             $Arango::DB::API::VERSION = '0.005';
4 4     4   1612 use Arango::DB::Database;
  4         10  
  4         151  
5 4     4   1645 use Arango::DB::Collection;
  4         10  
  4         111  
6              
7 4     4   24 use strict;
  4         7  
  4         74  
8 4     4   19 use warnings;
  4         7  
  4         93  
9 4     4   2794 use HTTP::Tiny;
  4         203150  
  4         176  
10 4     4   2898 use JSON;
  4         48475  
  4         33  
11 4     4   2170 use Clone 'clone';
  4         8634  
  4         262  
12 4     4   1693 use MIME::Base64 3.11 'encode_base64url';
  4         2409  
  4         239  
13 4     4   1809 use URI::Encode qw(uri_encode);
  4         45095  
  4         260  
14 4     4   1823 use JSON::Schema::Fit 0.02;
  4         16143  
  4         3152  
15              
16             my %API = (
17             'list_databases' => {
18             method => 'get',
19             uri => '_api/database',
20             params => { details => { type => 'boolean' }},
21             },
22             'create_database' => {
23             method => 'post',
24             uri => '_api/database',
25             params => { name => { type => 'string' }},
26             builder => sub {
27             my ($self, %params) = @_;
28             return Arango::DB::Database->_new(arango => $self, 'name' => $params{name});
29             },
30             },
31             'create_document' => {
32             method => 'post',
33             uri => '{database}_api/document/{collection}'
34             },
35             'create_collection' => {
36             method => 'post',
37             uri => '{database}_api/collection',
38             params => { name => { type => 'string' }},
39             builder => sub {
40             my ($self, %params) = @_;
41             return Arango::DB::Collection->_new(arango => $self, database => $params{database}, 'name' => $params{name});
42             },
43             },
44             'delete_collection' => {
45             method => 'delete',
46             uri => '{database}_api/collection/{name}'
47             },
48             'delete_database' => {
49             method => 'delete',
50             uri => '_api/database/{name}'
51             },
52             'list_collections' => {
53             method => 'get',
54             uri => '{database}_api/collection'
55             },
56             'all_keys' => {
57             method => 'put',
58             uri => '{database}_api/simple/all-keys',
59             params => { type => { type => 'string' }, collection => { type => 'string' } },
60             },
61             'version' => {
62             method => 'get',
63             uri => '_api/version',
64             params => { details => { type => 'boolean' } } ,
65             },
66             'cursor_next' => {
67             method => 'put',
68             uri => '{database}_api/cursor/{id}',
69             },
70             'create_cursor' => {
71             method => 'post',
72             uri => '{database}_api/cursor',
73             params => {
74             query => { type => 'string' },
75             count => { type => 'boolean' },
76             batchSize => { type => 'integer' },
77             cache => { type => 'boolean' },
78             memoryLimit => { type => 'integer' },
79             ttl => { type => 'integer' },
80             bindVars => { type => 'object', additionalProperties => 1 },
81             options => { type => 'object', additionalProperties => 0, properties => {
82             failOnWarning => { type => 'boolean' },
83             profile => { type => 'integer', maximum => 2, minimum => 0 }, # 0, 1, 2
84             maxTransactionSize => { type => 'integer' },
85             stream => { type => 'boolean' },
86             skipInaccessibleCollections => { type => 'boolean' },
87             maxWarningCount => { type => 'integer' },
88             intermediateCommitCount => { type => 'integer' },
89             satelliteSyncWait => { type => 'integer' },
90             fullCount => { type => 'boolean' },
91             intermediateCommitSize => { type => 'integer' },
92             'optimizer.rules' => { type => 'string' },
93             maxPlans => { type => 'integer' },
94             }
95             },
96             },
97             },
98            
99             );
100              
101              
102              
103             sub _check_options {
104 0     0     my ($params, $properties) = @_;
105 0           my $schema = { type => 'object', additionalProperties => 0, properties => $properties };
106 0           my $prepared_data = JSON::Schema::Fit->new()->get_adjusted($params, $schema);
107 0           return $prepared_data;
108             }
109              
110             sub _api {
111 0     0     my ($self, $action, $params) = @_;
112            
113 0           my $uri = $API{$action}{uri};
114              
115 0           my $params_copy = clone $params;
116              
117 0 0         $uri =~ s!\{database\}! defined $params->{database} ? "_db/$params->{database}/" : "" !e;
  0            
118 0           $uri =~ s/\{([^}]+)\}/$params->{$1}/g;
119            
120 0           my $url = "http://" . $self->{host} . ":" . $self->{port} . "/" . $uri;
121              
122 0 0 0       my $body = ref($params) eq "HASH" && exists $params->{body} ? $params->{body} : undef;
123 0 0         my $opts = ref($params) eq "HASH" ? $params : {};
124              
125 0 0         $opts = exists($API{$action}{params}) ? _check_options($opts, $API{$action}{params}) : {};
126              
127 0 0 0       if ($API{$action}{method} eq 'get' && scalar(keys %$opts)) {
128 0           $url .= "?" . join("&", map { "$_=" . uri_encode($opts->{$_} )} keys %$opts);
  0            
129             } else {
130 0 0 0       if ($body && ref($body) eq "HASH") {
    0          
131 0           $opts = { content => encode_json $body }
132             }
133             elsif (defined($body)) { # JSON
134 0           $opts = { content => $body }
135             }
136             else {
137 0           $opts = { content => encode_json $opts }
138             }
139             }
140            
141             #use Data::Dumper;
142             # print STDERR "\n -- $API{$action}{method} | $url\n";
143             #print STDERR "\n\nOPTS:\n\n", Dumper($opts);
144            
145              
146 0           my $response = $self->{http}->request($API{$action}{method}, $url, $opts);
147              
148 0 0         if ($response->{success}) {
149 0           my $ans = decode_json($response->{content});
150 0 0         if ($ans->{error}) {
    0          
151 0           return $ans;
152             } elsif (exists($API{$action}{builder})) {
153 0           return $API{$action}{builder}->( $self, %$params_copy );
154             } else {
155 0           return $ans;
156             }
157             }
158             else {
159 0           die "Arango::DB | ($response->{status}) $response->{reason}";
160             }
161             }
162              
163              
164              
165             1;
166              
167             __END__