arango-driver 3.5.0.alpha0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +1073 -0
  4. data/arango_opal.js +15 -0
  5. data/lib/arango-driver.rb +61 -0
  6. data/lib/arango.rb +96 -0
  7. data/lib/arango/aql.rb +188 -0
  8. data/lib/arango/collection.rb +575 -0
  9. data/lib/arango/collection/documents.rb +122 -0
  10. data/lib/arango/collection/edges.rb +149 -0
  11. data/lib/arango/collection/importing.rb +57 -0
  12. data/lib/arango/collection/indexes.rb +53 -0
  13. data/lib/arango/collection/replication.rb +24 -0
  14. data/lib/arango/collection/user.rb +28 -0
  15. data/lib/arango/cursor.rb +67 -0
  16. data/lib/arango/database.rb +188 -0
  17. data/lib/arango/database/analyzer.rb +21 -0
  18. data/lib/arango/database/aql_functions.rb +54 -0
  19. data/lib/arango/database/aql_queries.rb +114 -0
  20. data/lib/arango/database/aql_query_cache.rb +27 -0
  21. data/lib/arango/database/collections.rb +100 -0
  22. data/lib/arango/database/foxx_services.rb +103 -0
  23. data/lib/arango/database/graph_access.rb +27 -0
  24. data/lib/arango/database/http_route.rb +9 -0
  25. data/lib/arango/database/replication.rb +96 -0
  26. data/lib/arango/database/stream_transactions.rb +25 -0
  27. data/lib/arango/database/tasks.rb +67 -0
  28. data/lib/arango/database/transactions.rb +15 -0
  29. data/lib/arango/database/user.rb +26 -0
  30. data/lib/arango/database/view_access.rb +37 -0
  31. data/lib/arango/document.rb +443 -0
  32. data/lib/arango/edge.rb +164 -0
  33. data/lib/arango/error.rb +97 -0
  34. data/lib/arango/error_db.rb +27 -0
  35. data/lib/arango/foxx.rb +255 -0
  36. data/lib/arango/graph.rb +202 -0
  37. data/lib/arango/graph/basics.rb +39 -0
  38. data/lib/arango/graph/edge_access.rb +56 -0
  39. data/lib/arango/graph/vertex_access.rb +33 -0
  40. data/lib/arango/helper/collection_assignment.rb +13 -0
  41. data/lib/arango/helper/database_assignment.rb +14 -0
  42. data/lib/arango/helper/request_method.rb +45 -0
  43. data/lib/arango/helper/return.rb +21 -0
  44. data/lib/arango/helper/satisfaction.rb +28 -0
  45. data/lib/arango/helper/server_assignment.rb +13 -0
  46. data/lib/arango/helper/traversal.rb +12 -0
  47. data/lib/arango/index.rb +103 -0
  48. data/lib/arango/replication.rb +231 -0
  49. data/lib/arango/request.rb +92 -0
  50. data/lib/arango/request_batch.rb +174 -0
  51. data/lib/arango/result.rb +130 -0
  52. data/lib/arango/search_view.rb +23 -0
  53. data/lib/arango/server.rb +68 -0
  54. data/lib/arango/server/administration.rb +296 -0
  55. data/lib/arango/server/agency.rb +23 -0
  56. data/lib/arango/server/async.rb +51 -0
  57. data/lib/arango/server/batch.rb +35 -0
  58. data/lib/arango/server/config.rb +76 -0
  59. data/lib/arango/server/databases.rb +71 -0
  60. data/lib/arango/server/monitoring.rb +17 -0
  61. data/lib/arango/server/opal_support.rb +95 -0
  62. data/lib/arango/server/tasks.rb +69 -0
  63. data/lib/arango/server/user.rb +22 -0
  64. data/lib/arango/task.rb +223 -0
  65. data/lib/arango/transaction.rb +113 -0
  66. data/lib/arango/traversal.rb +212 -0
  67. data/lib/arango/user.rb +174 -0
  68. data/lib/arango/version.rb +3 -0
  69. data/lib/arango/vertex.rb +112 -0
  70. data/lib/arango/view.rb +124 -0
  71. data/lib/arango/view/basics.rb +25 -0
  72. metadata +296 -0
@@ -0,0 +1,164 @@
1
+ # === GRAPH VERTEX ===
2
+
3
+ module Arango
4
+ class Edge < Arango::Document
5
+ def initialize(name: nil, collection:, body: {}, rev: nil, from: nil,
6
+ to: nil)
7
+ assign_collection(collection)
8
+ body[:_key] ||= name
9
+ body[:_rev] ||= rev
10
+ body[:_from] ||= from
11
+ body[:_to] ||= to
12
+ body[:_id] ||= "#{@collection.name}/#{name}" unless name.nil?
13
+ assign_attributes(body)
14
+ end
15
+
16
+ # === DEFINE ===
17
+
18
+ attr_reader :collection, :database, :graph, :server
19
+
20
+ def collection=(collection)
21
+ satisfy_class?(collection, [Arango::Collection])
22
+ if collection.graph.nil?
23
+ raise Arango::Error.new err: :collection_does_not_have_a_graph, data:
24
+ {name_collection: collection.name, graph: nil}
25
+ end
26
+ @collection = collection
27
+ @graph = @collection.graph
28
+ @database = @collection.database
29
+ @server = @database.server
30
+ end
31
+ alias assign_collection collection=
32
+
33
+ # == GET ==
34
+
35
+ def retrieve(if_match: false)
36
+ headers = {}
37
+ headers[:"If-Match"] = @body[:_rev] if if_match
38
+ result = @graph.request("GET", "edge/#{@collection.name}/#{@body[:_key]}",
39
+ headers: headers, key: :edge)
40
+ return_element(result)
41
+ end
42
+
43
+ # == POST ==
44
+
45
+ def create(body: {}, wait_for_sync: nil)
46
+ body = @body.merge(body)
47
+ query = {
48
+ waitForSync: wait_for_sync,
49
+ _from: @body[:_from],
50
+ _to: @body[:_to]
51
+ }
52
+ result = @graph.request("POST", "edge/#{@collection.name}", body: body,
53
+ query: query, key: :edge)
54
+ return result if @server.async != false
55
+ body2 = result.clone
56
+ body = body.merge(body2)
57
+ assign_attributes(body)
58
+ return return_directly?(result) ? result : self
59
+ end
60
+
61
+ # == PUT ==
62
+
63
+ def replace(body: {}, wait_for_sync: nil, keep_null: nil, if_match: false)
64
+ query = {
65
+ waitForSync: wait_for_sync,
66
+ keepNull: keep_null
67
+ }
68
+ headers = {}
69
+ headers[:"If-Match"] = @body[:_rev] if if_match
70
+ result = @graph.request("PUT", "edge/#{@collection.name}/#{@body[:_key]}",
71
+ body: body, query: query, headers: headers, key: :edge)
72
+ return result if @server.async != false
73
+ body2 = result.clone
74
+ body = body.merge(body2)
75
+ assign_attributes(body)
76
+ return return_directly?(result) ? result : self
77
+ end
78
+
79
+ def update(body: {}, wait_for_sync: nil, if_match: false)
80
+ query = {waitForSync: wait_for_sync}
81
+ headers = {}
82
+ headers[:"If-Match"] = @body[:_rev] if if_match
83
+ result = @graph.request("PATCH", "edge/#{@collection.name}/#{@body[:_key]}",
84
+ body: body, query: query, headers: headers, key: :edge)
85
+ return result if @server.async != false
86
+ body2 = result.clone
87
+ body = body.merge(body2)
88
+ body = @body.merge(body)
89
+ assign_attributes(body)
90
+ return return_directly?(result) ? result : self
91
+ end
92
+
93
+ # === DELETE ===
94
+
95
+ def destroy(wait_for_sync: nil, if_match: false)
96
+ query = {waitForSync: wait_for_sync}
97
+ headers = {}
98
+ headers[:"If-Match"] = @body[:_rev] if if_match
99
+ result = @graph.request("DELETE", "edge/#{@collection.name}/#{@body[:_key]}",
100
+ query: query, headers: headers)
101
+ return_delete(result)
102
+ end
103
+
104
+ def from=(att)
105
+ att = att.id if att.is_a?(Arango::Document)
106
+ assign_attributes({_from: att})
107
+ end
108
+
109
+ def to=(att)
110
+ att = att.id if att.is_a?(Arango::Document)
111
+ assign_attributes({_to: att})
112
+ end
113
+
114
+ def set_up_from_or_to(attrs, var)
115
+ case var
116
+ when NilClass
117
+ @body[:"_#{attrs}"] = nil
118
+ when String
119
+ unless var.include?("/")
120
+ raise Arango::Error.new err: :attribute_is_not_valid, data:
121
+ {attribute: attrs, wrong_value: var}
122
+ end
123
+ @body[:"_#{attrs}"] = var
124
+ when Arango::Document
125
+ @body[:"_#{attrs}"] = var.id
126
+ @from = var if attrs == "from"
127
+ @to = var if attrs == "to"
128
+ else
129
+ raise Arango::Error.new err: :attribute_is_not_valid, data:
130
+ {attribute: attrs, wrong_value: var}
131
+ end
132
+ end
133
+ private :set_up_from_or_to
134
+
135
+ def from(string: false)
136
+ return @body[:_from] if string
137
+ @from ||= retrieve_instance_from_and_to(@body[:_from])
138
+ return @from
139
+ end
140
+
141
+ def to(string: false)
142
+ return @body[:_to] if string
143
+ @to ||= retrieve_instance_from_and_to(@body[:_to])
144
+ return @to
145
+ end
146
+
147
+ def retrieve_instance_from_and_to(var)
148
+ case var
149
+ when NilClass
150
+ return nil
151
+ when String
152
+ collection_name, document_name = var.split("/")
153
+ collection = Arango::Collection.new collection_name, database: @database
154
+ if @graph.nil?
155
+ return Arango::Document.new(document_name, collection: collection)
156
+ else
157
+ collection.graph = @graph
158
+ return Arango::Vertex.new(name: document_name, collection: collection)
159
+ end
160
+ end
161
+ end
162
+ private :retrieve_instance_from_and_to
163
+ end
164
+ end
@@ -0,0 +1,97 @@
1
+ # === ERROR ===
2
+
3
+ module Arango
4
+ class Error < StandardError
5
+ ARANGODB_ERRORS = {
6
+ no_other_aql_next: {
7
+ code: 10001, message: "No other values with AQL next"
8
+ },
9
+ no_other_simple_next: {
10
+ code: 10002, message: "No other values with AQL next"
11
+ },
12
+ is_a_edge_collection: {
13
+ code: 10003, message: "This collection is an Edge collection"
14
+ },
15
+ is_a_document_collection: {
16
+ code: 10004, message: "This collection is a Document collection"
17
+ },
18
+ database_graph_no_same_as_collection_database: {
19
+ code: 10005, message: "Database of graph is not the same as the class"
20
+ },
21
+ wrong_type_instead_of_expected_one: {
22
+ code: 10006, message: "Expected a type, received another"
23
+ },
24
+ no_other_export_next: {
25
+ code: 10007, message: "No other values with AQL next"
26
+ },
27
+ no_aql_id_available: {
28
+ code: 10008, message: "AQL does not have id. It could have already been killed"
29
+ },
30
+ id_is_not_valid: {
31
+ code: 10009, message: "Given attribute is not a valid document id or an Arango::Document"
32
+ },
33
+ collection_does_not_have_a_graph: {
34
+ code: 10010, message: "Collection does not have a graph"
35
+ },
36
+ arangodb_did_not_return_a_valid_result: {
37
+ code: 10011, message: "ArangoDB didn't return a valid result"
38
+ },
39
+ read_or_write_should_be_string_or_collections: {
40
+ code: 10012, message: "read or write should be an array of name classes or Arango::Collections"
41
+ },
42
+ wrong_class: {
43
+ code: 10013, message: "Wrong class"
44
+ },
45
+ wrong_element: {
46
+ code: 10014, message: "Element is not part of the list"
47
+ },
48
+ orphan_collection_used_by_edge_definition: {
49
+ code: 10015, message: "Orphan collection is already used by an edge definition"
50
+ },
51
+ impossible_to_parse_arangodb_response: {
52
+ code: 10016, message: "Impossible to parse ArangoDB response"
53
+ },
54
+ batch_query_not_valid: {
55
+ code: 10017, message: "Query is not valid"
56
+ },
57
+ arangorb_didnt_return_a_valid_result: {
58
+ code: 10018, message: "ArangoRB didn't return a valid result"
59
+ },
60
+ impossible_to_connect_with_database: {
61
+ code: 10019, message: "Impossible to connect with database"
62
+ },
63
+ you_cannot_assign_from_or_to_to_a_vertex: {
64
+ code: 10020, message: "You cannot assign from or to to a Vertex"
65
+ },
66
+ wrong_start_vertex_type: {
67
+ code: 10021, message: "Starting vertex should be an Arango::Vertex, an Arango::Document (not Edge) or a valid vertex id"
68
+ },
69
+ database_undefined_for_traversal: {
70
+ code: 10022, message: "Database undefined for traversal"
71
+ },
72
+ edge_collection_should_be_of_type_edge: {
73
+ code: 10022, message: "Database undefined for traversal"
74
+ }
75
+ }.freeze
76
+
77
+ def initialize(err:, data: nil, skip_assignment: false)
78
+ unless skip_assignment
79
+ @message = ARANGODB_ERRORS[err][:message]
80
+ @code = ARANGODB_ERRORS[err][:code]
81
+ @internal_code = err
82
+ @data = data
83
+ end
84
+ super(@message)
85
+ end
86
+ attr_reader :data, :code, :message
87
+
88
+ def to_h
89
+ {
90
+ message: @message,
91
+ code: @code,
92
+ data: @data,
93
+ internal_code: @internal_code
94
+ }.delete_if{|k,v| v.nil?}
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,27 @@
1
+ module Arango
2
+ class ErrorDB < Arango::Error
3
+ def initialize(message:, code:, data:, error_num:, action: nil, url: nil, request:)
4
+ @message = message
5
+ @code = code
6
+ @data = data
7
+ @error_num = error_num
8
+ @action = action
9
+ @url = url
10
+ @request = request
11
+ super(err: nil, skip_assignment: true)
12
+ end
13
+ attr_reader :action, :code, :data, :error_num, :message, :request, :url
14
+
15
+ def to_h
16
+ {
17
+ action: @action,
18
+ url: @url,
19
+ request: @request,
20
+ message: @message,
21
+ code: @code,
22
+ data: @data,
23
+ errorNum: @error_num
24
+ }.delete_if{|k,v| v.nil?}
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,255 @@
1
+ # === FOXX ===
2
+
3
+ module Arango
4
+ class Foxx
5
+ include Arango::Helper::Satisfaction
6
+ include Arango::Helper::Return
7
+ include Arango::Helper::DatabaseAssignment
8
+
9
+ def initialize(database:, body: {}, mount:, development: nil, legacy: nil,
10
+ provides: nil, name: nil, version: nil, type: "application/json",
11
+ setup: nil, teardown: nil, cache_name: nil)
12
+ assign_database(database)
13
+ unless cache_name.nil?
14
+ @cache_name = cache_name
15
+ @server.cache.save(:foxx, cache_name, self)
16
+ end
17
+ assign_attributes(body)
18
+ assign_type(type)
19
+ @development ||= development
20
+ @legacy ||= legacy
21
+ @mount ||= mount
22
+ @name ||= name
23
+ @provides ||= provides
24
+ @setup ||= setup
25
+ @teardown ||= teardown
26
+ @version ||= version
27
+ end
28
+
29
+ # === DEFINE ===
30
+
31
+ attr_reader :body, :cache_name, :database, :server, :type
32
+ attr_accessor :development, :legacy, :mount, :name, :provides, :setup, :teardown, :version
33
+
34
+ def body=(result)
35
+ if result.is_a?(Hash)
36
+ @body = result
37
+ @development = result[:development] || @development
38
+ @legacy = result[:legacy] || @legacy
39
+ @mount = result[:mount] || @mount
40
+ @name = result[:name] || @name
41
+ @provides = result[:provides] || @provides
42
+ @version = result[:version] || @version
43
+ if @server.active_cache && @cache_name.nil?
44
+ @cache_name = "#{@database.name}/#{@mount}"
45
+ @server.cache.save(:task, @cache_name, self)
46
+ end
47
+ end
48
+ end
49
+ alias assign_attributes body=
50
+
51
+ def type=(type)
52
+ satisfy_category?(type, %w[application/zip zip application/javascript javascript application/json json multipart/form-data data])
53
+ type = "application/#{type}" if %w[zip javascript json].include?(type)
54
+ type = "multipart/form-data" if type == "data"
55
+ @type = type
56
+ end
57
+ alias assign_type type=
58
+
59
+ # === TO HASH ===
60
+
61
+ def to_h
62
+ {
63
+ cache_name: @cache_name,
64
+ database: @database.name,
65
+ development: @development,
66
+ legacy: @legacy,
67
+ mount: @mount,
68
+ name: @name,
69
+ provides: @provides,
70
+ teardown: @teardown,
71
+ type: @type,
72
+ version: @version
73
+ }.delete_if{|k,v| v.nil?}
74
+ end
75
+
76
+ def return_foxx(result, val=nil)
77
+ return result if @server.async != false
78
+ case val
79
+ when :configuration
80
+ @configuration = result
81
+ when :dependencies
82
+ @dependencies = result
83
+ else
84
+ assign_attributes(result)
85
+ end
86
+ return return_directly?(result) ? result : self
87
+ end
88
+ private :return_foxx
89
+
90
+ # === ACTIONS ===
91
+
92
+ def retrieve
93
+ query = {mount: @mount}
94
+ result = @database.request("GET", url: "_api/foxx/service")
95
+ return_foxx(result)
96
+ end
97
+
98
+ def create(body: @body, type: @type, development: @development,
99
+ setup: @setup, legacy: @legacy)
100
+ headers = { Accept: type }
101
+ skip_to_json = type != "application/json"
102
+ query = {
103
+ mount: @mount,
104
+ setup: setup,
105
+ development: development,
106
+ legacy: legacy
107
+ }
108
+ result = @database.request("POST",
109
+ url: "_api/foxx", body: body, headers: headers,
110
+ skip_to_json: skip_to_json, query: query)
111
+ return_foxx(result)
112
+ end
113
+
114
+ def destroy(teardown: @teardown)
115
+ query = {
116
+ mount: @mount,
117
+ teardown: teardown
118
+ }
119
+ result = @database.request("DELETE", "_api/foxx/service", query: query)
120
+ return_foxx(result)
121
+ end
122
+
123
+ def replace(body: @body, type: @type, teardown: @teardown, setup: @setup,
124
+ legacy: @legacy)
125
+ headers = { Accept: type }
126
+ skip_to_json = type != "application/json"
127
+ query = {
128
+ mount: @mount,
129
+ setup: setup,
130
+ teardown: teardown,
131
+ legacy: legacy
132
+ }
133
+ result = @database.request("PUT", "_api/foxx/service", body: body,
134
+ headers: headers, skip_to_json: skip_to_json, query: query)
135
+ return_foxx(result)
136
+ end
137
+
138
+ def update(body: @body, type: @type, teardown: @teardown,
139
+ setup: @setup, legacy: @legacy)
140
+ assign_type(type)
141
+ headers = { Accept: type }
142
+ skip_to_json = @type != "application/json"
143
+ query = {
144
+ mount: @mount,
145
+ setup: setup,
146
+ teardown: teardown,
147
+ legacy: legacy
148
+ }
149
+ result = @database.request("PATCH", "_api/foxx/service", body: body,
150
+ headers: headers, skip_to_json: skip_to_json, query: query)
151
+ return_foxx(result)
152
+ end
153
+
154
+ # === CONFIGURATION ===
155
+
156
+ def retrieve_configuration
157
+ query = { mount: @mount }
158
+ result = @database.request("GET", "_api/foxx/configuration", query: query)
159
+ return_foxx(result, :configuration)
160
+ end
161
+
162
+ def update_configuration(body:)
163
+ query = { mount: @mount }
164
+ result = @database.request("PATCH", "_api/foxx/configuration", query: query, body: body)
165
+ return_foxx(result, :configuration)
166
+ end
167
+
168
+ def replace_configuration(body:)
169
+ query = { mount: @mount }
170
+ result = @database.request("PUT", "_api/foxx/configuration", query: query, body: body)
171
+ return_foxx(result, :configuration)
172
+ end
173
+
174
+ # === DEPENDENCY ===
175
+
176
+ def retrieve_dependencies
177
+ query = { mount: @mount }
178
+ result = @database.request("GET", "_api/foxx/dependencies", query: query)
179
+ return_foxx(result, :dependencies)
180
+ end
181
+
182
+ def update_dependencies(body:)
183
+ query = { mount: @mount }
184
+ result = @database.request("PATCH", "_api/foxx/dependencies", query: query, body: body)
185
+ return_foxx(result, :dependencies)
186
+ end
187
+
188
+ def replace_dependencies(body:)
189
+ query = { mount: @mount }
190
+ result = @database.request("PUT", "_api/foxx/dependencies", query: query, body: body)
191
+ return_foxx(result, :dependencies)
192
+ end
193
+
194
+ # === MISCELLANEOUS
195
+
196
+ def scripts
197
+ query = { mount: @mount }
198
+ @database.request("GET", "_api/foxx/scripts", query: query)
199
+ end
200
+
201
+ def run_script(name:, body: {})
202
+ query = { mount: @mount }
203
+ @database.request("POST", "_api/foxx/scripts/#{name}", query: query, body: body)
204
+ end
205
+
206
+ def tests(reporter: nil, idiomatic: nil)
207
+ satisfy_category?(reporter, [nil, "default", "suite", "stream", "xunit", "tap"])
208
+ headers = {}
209
+ headers[:"Content-Type"] = case reporter
210
+ when "stream"
211
+ "application/x-ldjson"
212
+ when "tap"
213
+ "text/plain, text/*"
214
+ when "xunit"
215
+ "application/xml, text/xml"
216
+ else
217
+ nil
218
+ end
219
+ query = { mount: @mount }
220
+ @database.request("GET", "_api/foxx/scripts", query: query, headers: headers)
221
+ end
222
+
223
+ def enable_development
224
+ query = { mount: @mount }
225
+ @database.request("POST", "_api/foxx/development", query: query)
226
+ end
227
+
228
+ def disable_development
229
+ query = { mount: @mount }
230
+ @database.request("DELETE", "_api/foxx/development", query: query)
231
+ end
232
+
233
+ def readme
234
+ query = { mount: @mount }
235
+ @database.request("GET", "_api/foxx/readme", query: query)
236
+ end
237
+
238
+ def swagger
239
+ query = { mount: @mount }
240
+ @database.request("GET", "_api/foxx/swagger", query: query)
241
+ end
242
+
243
+ def download(path:, warning: @server.warning)
244
+ query = { mount: @mount }
245
+ @server.download("POST", "_db/#{@database.name}/_api/foxx/download",
246
+ path: path, query: query)
247
+ puts "File saved in #{path}" if warning
248
+ end
249
+
250
+ def commit(body:, replace: nil)
251
+ query = { replace: replace }
252
+ @database.request("POST", "_api/foxx/commit", body: body, query: query)
253
+ end
254
+ end
255
+ end