yax-fauna 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f2163449ff0b2f3f9eb5abff36ae23d33cfb53bb81f8688f4a8b3b1acec51010
4
+ data.tar.gz: ba7a3a18d2492d6b3b32c052327f7272b1bfdf979a018c6c9b44fc9739dd0386
5
+ SHA512:
6
+ metadata.gz: 1ab8570d7756839afa10ad19411c8928d1db9ee409da600d795382b8dfd98b508f96b05ec6bf7ea54d426e97eec95a05fb999af54a2bd1be6a5c5da97d7eef3d
7
+ data.tar.gz: 18d9e7727723f47073eb4a957846736351c0af9af881149c5f3c573b42ef9e97f9d1938c60da79b2636b793ee68ba49bc064b5d671eea7358407c14183f026d2
@@ -0,0 +1,51 @@
1
+ 4.0.0.pre.1
2
+ * Adds `ngram` function.
3
+ * Added `is_empty` and `is_nonempty` functions.
4
+ * Added `to_string`, `to_number`, `to_time`, and `to_date` functions.
5
+ * Reverses the argument order of append and prepend functions.
6
+ * Fixed serialization to correctly wrap objects that implement `to_h` or `to_hash`
7
+ (unsupported objects are now explictly rejected with a `Fauna::SerializationError`).
8
+ * Add support for the X-Last-Seen-Txn header
9
+
10
+ 3.0.0
11
+ * Adds support for recursive references.
12
+ * Removed REST api support from `Client`.
13
+ * Added `abort` function.
14
+ * Added `normalizer` argument to `casefold` function.
15
+ * Added `new_id` function.
16
+ * Deprecated `next_id` function in favor of `new_id`.
17
+ * Added `identity` and `has_identity` functions.
18
+ * Added `singleton` and `events` functions.
19
+ * Added `select_all` function.
20
+
21
+ 2.4.0
22
+ * Handle HTTP errors 502 and 504 as `Fauna::UnavailableError`.
23
+ * Added support for user-defined functions.
24
+ * Added support for the `@query` type (via `Fauna::QueryV`).
25
+ * Added `create_function`, `function`, and `call` query functions.
26
+
27
+ 2.3.0
28
+ * Change default domain to `db.fauna.com`.
29
+ * Added `key_from_secret` and `at` query functions.
30
+ * Added support for `@bytes` type (via `Fauna::Bytes`).
31
+
32
+ 2.2.0
33
+ * Added `create_class`, `create_index`, `create_database`, `create_key`, `database`, `class`,
34
+ and `index` query functions.
35
+ * Removed `count` query function.
36
+ * Raises `Fauna::UnavailableError` for all 503s and for Faraday network errors.
37
+ * Fix documentation errors and update links.
38
+
39
+ 2.1.2
40
+ * Change default domain to `cloud.faunadb.com`.
41
+
42
+ 2.1.1
43
+ * Use persistent connections (via the `net-http-persistent` adapter) by default.
44
+
45
+ 2.1.0
46
+ * Added paginate helper.
47
+ * Improved exception messages (now include FaunaDB errors).
48
+ * Added `ref` and `next_id` query functions.
49
+
50
+ 2.0.0
51
+ * Complete rewrite for API 2.0. Not backwards compatible with the old client or api.
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rake'
4
+ gem 'jruby-openssl', platform: :jruby
5
+
6
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,12 @@
1
+ Copyright 2017 Fauna, Inc.
2
+
3
+ Licensed under the Mozilla Public License, Version 2.0 (the "License"); you may
4
+ not use this software except in compliance with the License. You may obtain a
5
+ copy of the License at
6
+
7
+ http://mozilla.org/MPL/2.0/
8
+
9
+ Unless required by applicable law or agreed to in writing, software distributed
10
+ under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11
+ CONDITIONS OF ANY KIND, either express or implied. See the License for the
12
+ specific language governing permissions and limitations under the License.
@@ -0,0 +1,148 @@
1
+ # FaunaDB
2
+
3
+ [![Coverage Status](https://img.shields.io/codecov/c/github/fauna/faunadb-ruby/master.svg?maxAge=21600)](https://codecov.io/gh/fauna/faunadb-ruby/branch/master)
4
+ [![Gem Version](https://img.shields.io/gem/v/fauna.svg?maxAge=21600)](https://rubygems.org/gems/fauna)
5
+ [![License](https://img.shields.io/badge/license-MPL_2.0-blue.svg?maxAge=2592000)](https://raw.githubusercontent.com/fauna/faunadb-ruby/master/LICENSE)
6
+
7
+ Ruby driver for [FaunaDB](https://fauna.com).
8
+
9
+ ## Installation
10
+
11
+ The FaunaDB ruby driver is distributed as a gem. Install it via:
12
+
13
+ $ gem install fauna
14
+
15
+ Or if you use Bundler, add it to your application's `Gemfile`:
16
+
17
+ gem 'fauna'
18
+
19
+ And then execute:
20
+
21
+ $ bundle
22
+
23
+ ## Documentation
24
+
25
+ The driver documentation is [hosted on GitHub Pages](https://fauna.github.io/faunadb-ruby/).
26
+
27
+ Please see the [FaunaDB Documentation](https://fauna.com/documentation) for
28
+ a complete API reference, or look in
29
+ [`/test`](https://github.com/fauna/faunadb-ruby/tree/master/test) for more
30
+ examples.
31
+
32
+ ## Compatibility
33
+
34
+ Tested and compatible with the following ruby versions:
35
+
36
+ * MRI 1.9.3
37
+ * MRI 2.2.3
38
+ * Jruby 1.7.19
39
+
40
+ ## Basic Usage
41
+
42
+ First, require the gem:
43
+
44
+ ```ruby
45
+ require 'fauna'
46
+ ```
47
+
48
+ ### Creating a Client
49
+
50
+ All API requests pass through a `Fauna::Client`. Creating a client
51
+ requires either an admin key, server key, client key, or a token.
52
+
53
+ ```ruby
54
+ server_key = 'ls8AkXLdakAAAALPAJFy3LvQAAGwDRAS_Prjy6O8VQBfQAlZzwAA'
55
+ ```
56
+
57
+ Now we can make a database-level client:
58
+
59
+ ```ruby
60
+ $fauna = Fauna::Client.new(secret: server_key)
61
+ ```
62
+
63
+ You can optionally configure an `observer` on the client. To ease
64
+ debugging, we provide a simple logging observer at
65
+ `Fauna::ClientLogger.logger`, which you can configure as such:
66
+
67
+ ```ruby
68
+ require 'logger'
69
+ logger = Logger.new(STDERR)
70
+ observer = Fauna::ClientLogger.logger { |log| logger.debug(log) }
71
+
72
+ $fauna = Fauna::Client.new(
73
+ secret: server_key,
74
+ observer: observer)
75
+ ```
76
+
77
+ ### Using the Client
78
+
79
+ Now that we have a client, we can start performing queries:
80
+
81
+ ```ruby
82
+ # Create a class
83
+ $fauna.query { create ref('classes'), name: 'users' }
84
+
85
+ # Create an instance of the class
86
+ taran = $fauna.query do
87
+ create ref('classes/users'), data: { email: 'taran@example.com' }
88
+ end
89
+
90
+ # Update the instance
91
+ taran = $fauna.query do
92
+ update taran[:ref], data: {
93
+ name: 'Taran',
94
+ profession: 'Pigkeeper'
95
+ }
96
+ end
97
+
98
+ # Page through a set
99
+ pigkeepers = Fauna::Query.expr { match(ref('indexes/users_by_profession'), 'Pigkeeper') }
100
+ oracles = Fauna::Query.expr { match(ref('indexes/users_by_profession'), 'Oracle') }
101
+
102
+ $fauna.query { paginate(union(pigkeepers, oracles)) }
103
+
104
+ # Delete the user
105
+ $fauna.query { delete taran[:ref] }
106
+ ```
107
+
108
+ ## Running Tests
109
+
110
+ You can run tests against FaunaDB Cloud yourself.
111
+ [Create an admin key](https://fauna.com/account/keys) and set
112
+ `FAUNA_ROOT_KEY` environment variable to it's secret. Then run `rake spec`:
113
+
114
+ ```bash
115
+ export FAUNA_ROOT_KEY='kqnPAbijGhkgAAC03-36hjCvcTnWf4Pl8w97UE1HeWo'
116
+ rake spec
117
+ ```
118
+
119
+ To run a single test, use e.g. `ruby test/client_test.rb`.
120
+
121
+ Coverage is automatically run as part of the tests. After running tests, check
122
+ `coverage/index.html` for the coverage report. If using jruby, use
123
+ `JRUBY_OPTS="--debug" bundle exec rake spec` to ensure coverage is generated
124
+ correctly.
125
+
126
+ Tests can also be run via a Docker container with
127
+ `FAUNA_ROOT_KEY="your-cloud-secret" make docker-test` (an alternate
128
+ Alpine-based Ruby image can be provided via `RUNTIME_IMAGE`).
129
+
130
+ ## Contributing
131
+
132
+ GitHub pull requests are very welcome.
133
+
134
+ ## LICENSE
135
+
136
+ Copyright 2017 [Fauna, Inc.](https://fauna.com/)
137
+
138
+ Licensed under the Mozilla Public License, Version 2.0 (the
139
+ "License"); you may not use this software except in compliance with
140
+ the License. You may obtain a copy of the License at
141
+
142
+ [http://mozilla.org/MPL/2.0/](http://mozilla.org/MPL/2.0/)
143
+
144
+ Unless required by applicable law or agreed to in writing, software
145
+ distributed under the License is distributed on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied. See the License for the specific language governing
148
+ permissions and limitations under the License.
@@ -0,0 +1,13 @@
1
+ require 'rspec/core/rake_task'
2
+ require 'rdoc/task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ RDoc::Task.new do |rdoc|
7
+ rdoc.main = 'README.md'
8
+ rdoc.rdoc_dir = 'doc'
9
+ rdoc.rdoc_files.include('README.md', 'lib/fauna.rb', 'lib/fauna/*.rb')
10
+ end
11
+
12
+ task prerelease: [:spec, :install]
13
+ task default: :spec
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require './lib/fauna/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'yax-fauna'
6
+ s.version = Fauna::VERSION.dup
7
+ s.author = 'Forked from Fauna, Inc.'
8
+ s.email = 'daniel@danielkehoe.com'
9
+ s.summary = 'FaunaDB Ruby driver'
10
+ s.description = 'Ruby driver for FaunaDB.'
11
+ s.homepage = 'https://github.com/yaxdotcom/yax-faunadb-ruby'
12
+ s.license = 'MPL-2.0'
13
+
14
+ s.files = %w(CHANGELOG Gemfile LICENSE README.md Rakefile fauna.gemspec lib/fauna.rb) + Dir.glob('lib/fauna/**') + Dir.glob('spec/**')
15
+ s.extra_rdoc_files = %w(CHANGELOG LICENSE README.md)
16
+ s.rdoc_options = %w(--line-numbers --title Fauna --main README.md)
17
+ s.test_files = Dir.glob('spec/**')
18
+ s.require_paths = ['lib']
19
+
20
+ s.add_runtime_dependency 'faraday', '~> 1.0'
21
+ s.add_runtime_dependency 'net-http-persistent', '~> 2.9'
22
+ s.add_runtime_dependency 'json', '~> 2.3'
23
+ s.add_development_dependency 'rspec', '~> 3.4'
24
+ s.add_development_dependency 'simplecov-json', '~> 0.2.0'
25
+ s.add_development_dependency 'rspec_junit_formatter', '~> 0.3.0'
26
+ end
@@ -0,0 +1,25 @@
1
+ require 'json'
2
+ require 'logger'
3
+ require 'uri'
4
+ require 'faraday'
5
+ require 'cgi'
6
+ require 'zlib'
7
+ require 'time'
8
+ require 'base64'
9
+
10
+ ##
11
+ # Main namespace for the FaunaDB driver.
12
+ module Fauna; end
13
+
14
+ require 'fauna/deprecate'
15
+ require 'fauna/version'
16
+ require 'fauna/util'
17
+ require 'fauna/errors'
18
+ require 'fauna/client'
19
+ require 'fauna/client_logger'
20
+ require 'fauna/context'
21
+ require 'fauna/objects'
22
+ require 'fauna/query'
23
+ require 'fauna/json'
24
+ require 'fauna/page'
25
+ require 'fauna/request_result'
@@ -0,0 +1,253 @@
1
+ require 'thread'
2
+
3
+ module Fauna
4
+ ##
5
+ # The Ruby client for FaunaDB.
6
+ #
7
+ # All methods return a converted JSON response.
8
+ # This is a Hash containing Arrays, ints, floats, strings, and other Hashes.
9
+ # Hash keys are always Symbols.
10
+ #
11
+ # Any Ref, SetRef, Time or Date values in it will also be parsed.
12
+ # (So instead of <code>{ "@ref": { "id": "123", "class": { "@ref": { "id": "frogs", "class": { "@ref": { "id": "classes" } } } } } }</code>,
13
+ # you will get <code>Fauna::Ref.new("123", Fauna::Ref.new("frogs", Fauna::Native.classes))</code>).
14
+ class Client
15
+ # The domain requests will be sent to.
16
+ attr_reader :domain
17
+ # Scheme used when sending requests (either +http+ or +https+).
18
+ attr_reader :scheme
19
+ # Port used when sending requests.
20
+ attr_reader :port
21
+ # An array of the user and pass used for authentication when sending requests.
22
+ attr_reader :credentials
23
+ # Read timeout in seconds.
24
+ attr_reader :read_timeout
25
+ # Open timeout in seconds.
26
+ attr_reader :connection_timeout
27
+ # Callback that will be passed a +RequestResult+ after every completed request.
28
+ attr_reader :observer
29
+ # Faraday[https://github.com/lostisland/faraday] adapter in use.
30
+ attr_reader :adapter
31
+
32
+ # Maintains a thread-safe last seen transaction time. Clients
33
+ # copied using #with_secret will share the same LastSeen object.
34
+ class LastSeen
35
+ def initialize()
36
+ @mutex = Mutex.new
37
+ @time = nil
38
+ end
39
+
40
+ def time
41
+ @mutex.synchronize do
42
+ @time
43
+ end
44
+ end
45
+
46
+ def update(time)
47
+ @mutex.synchronize do
48
+ if @time.nil?
49
+ @time = time
50
+ elsif @time < time
51
+ @time = time
52
+ end
53
+ end
54
+ end
55
+
56
+ end
57
+
58
+ ##
59
+ # Create a new Client.
60
+ #
61
+ # +params+:: A list of parameters to configure the connection with.
62
+ # +:domain+:: The domain to send requests to.
63
+ # +:scheme+:: Scheme to use when sending requests (either +http+ or +https+).
64
+ # +:port+:: Port to use when sending requests.
65
+ # +:secret+:: Credentials to use when sending requests. User and pass must be separated by a colon.
66
+ # +:read_timeout+:: Read timeout in seconds.
67
+ # +:connection_timeout+:: Open timeout in seconds.
68
+ # +:observer+:: Callback that will be passed a RequestResult after every completed request.
69
+ # +:adapter+:: Faraday[https://github.com/lostisland/faraday] adapter to use. Either can be a symbol for the adapter, or an array of arguments.
70
+ def initialize(params = {})
71
+ @domain = params[:domain] || 'db.fauna.com'
72
+ @scheme = params[:scheme] || 'https'
73
+ @port = params[:port] || (scheme == 'https' ? 443 : 80)
74
+ @read_timeout = params[:read_timeout] || 60
75
+ @connection_timeout = params[:connection_timeout] || 60
76
+ @observer = params[:observer]
77
+ @adapter = params[:adapter] || :net_http_persistent
78
+ @last_seen = LastSeen.new
79
+ init_credentials(params[:secret])
80
+
81
+ init_connection
82
+ end
83
+
84
+ ##
85
+ # Create a new client from the existing config with a given secret.
86
+ #
87
+ # +:secret+:: Credentials to use when sending requests. User and pass must be separated by a colon.
88
+ def with_secret(secret)
89
+ with_dup do |client|
90
+ client.send(:init_credentials, secret)
91
+ end
92
+ end
93
+
94
+ ##
95
+ # Issues a query to FaunaDB.
96
+ #
97
+ # Queries are built via the Query helpers. See {FaunaDB Query API}[https://fauna.com/documentation/queries]
98
+ # for information on constructing queries.
99
+ #
100
+ # +expression+:: A query expression
101
+ # +expr_block+:: May be provided instead of expression. Block is used to build an expression with Fauna.query.
102
+ #
103
+ # Example using expression:
104
+ #
105
+ # <code>client.query(Fauna::Query.add(1, 2, Fauna::Query.subtract(3, 2)))</code>
106
+ #
107
+ # Example using block:
108
+ #
109
+ # <code>client.query { add(1, 2, subtract(3, 2)) }</code>
110
+ #
111
+ # Reference: {Executing FaunaDB Queries}[https://fauna.com/documentation#queries]
112
+ #
113
+ # :category: Query Methods
114
+ def query(expression = nil, &expr_block)
115
+ if expr_block.nil?
116
+ execute(:post, :'', nil, Fauna::Query::Expr.wrap(expression))
117
+ else
118
+ execute(:post, :'', nil, Fauna::Query.expr(&expr_block))
119
+ end
120
+ end
121
+
122
+ ##
123
+ # Creates a Fauna::Page for paging/iterating over a set.
124
+ #
125
+ # +set+:: A set query to paginate over.
126
+ # +params+:: A list of parameters to pass to {paginate}[https://fauna.com/documentation/queries#read_functions-paginate_set].
127
+ # +fauna_map+:: Optional block to wrap the generated paginate query with. The block will be run in a query context.
128
+ # The paginate query will be passed into the block as an argument.
129
+ def paginate(set, params = {}, &fauna_map)
130
+ Fauna::Page.new(self, set, params, &fauna_map)
131
+ end
132
+
133
+ ##
134
+ # Ping FaunaDB.
135
+ #
136
+ # Reference: {FaunaDB Rest API}[https://fauna.com/documentation#rest-other].
137
+ #
138
+ # :category: REST Methods
139
+ def ping(params = {})
140
+ execute(:get, :ping, params)
141
+ end
142
+
143
+ private
144
+
145
+ def with_dup
146
+ new_client = self.dup
147
+ yield new_client
148
+ new_client.send(:init_connection)
149
+ new_client
150
+ end
151
+
152
+ def init_credentials(secret)
153
+ @credentials = secret.to_s.split(':', 2)
154
+ end
155
+
156
+ def init_connection
157
+ @connection = Faraday.new(
158
+ url: "#{scheme}://#{domain}:#{port}/",
159
+ headers: {
160
+ 'Accept-Encoding' => 'gzip,deflate',
161
+ 'Content-Type' => 'application/json;charset=utf-8',
162
+ 'User-Agent' => "FaunaDB-Ruby/#{Fauna::VERSION}",
163
+ 'X-FaunaDB-API-Version' => '2.1'
164
+ },
165
+ request: { timeout: read_timeout, open_timeout: connection_timeout },
166
+ ) do |conn|
167
+ # Let us specify arguments so we can set stubs for test adapter
168
+ conn.adapter(*Array(adapter))
169
+ conn.basic_auth(credentials[0].to_s, credentials[1].to_s)
170
+ conn.response :fauna_decode
171
+ end
172
+ end
173
+
174
+ def execute(action, path, query = nil, data = nil)
175
+ path = path.to_s
176
+
177
+ start_time = Time.now
178
+ begin
179
+ response = perform_request action, path, query, data
180
+ rescue Faraday::ClientError => e
181
+ end_time = Time.now
182
+
183
+ message = e.class.name
184
+ message += ": #{e.message}" unless e.message.nil?
185
+
186
+ request_result = RequestResult.new(self,
187
+ action, path, query, data,
188
+ nil, nil, nil, nil,
189
+ start_time, end_time)
190
+ raise UnexpectedError.new(message, request_result)
191
+ end
192
+ end_time = Time.now
193
+
194
+ response_raw = response.body
195
+ response_json = FaunaJson.json_load_or_nil response_raw
196
+ response_content = FaunaJson.deserialize response_json unless response_json.nil?
197
+
198
+ request_result = RequestResult.new(self,
199
+ action, path, query, data,
200
+ response_raw, response_content, response.status, response.headers,
201
+ start_time, end_time)
202
+
203
+
204
+ if response.headers.key?('X-Txn-Time')
205
+ time = response.headers['X-Txn-Time'].to_i
206
+
207
+ @last_seen.update(time)
208
+ end
209
+
210
+ @observer.call(request_result) unless @observer.nil?
211
+
212
+ FaunaError.raise_for_status_code(request_result)
213
+ UnexpectedError.get_or_raise request_result, response_content, :resource
214
+ end
215
+
216
+ def perform_request(action, path, query, data)
217
+ @connection.send(action) do |req|
218
+ req.params = query.delete_if { |_, v| v.nil? } unless query.nil?
219
+ req.body = FaunaJson.to_json(data) unless data.nil?
220
+
221
+ last_txn = @last_seen.time
222
+ unless last_txn.nil?
223
+ req.headers['X-Last-Seen-Txn'] = last_txn.to_s
224
+ end
225
+
226
+ req.url(path || '')
227
+ end
228
+ rescue Faraday::ConnectionFailed, Faraday::TimeoutError, Faraday::SSLError => e
229
+ raise UnavailableError.new(e)
230
+ end
231
+ end
232
+
233
+ # Middleware for decompressing responses
234
+ class FaunaDecode < Faraday::Middleware # :nodoc:
235
+ def call(env)
236
+ @app.call(env).on_complete do |response_env|
237
+ raw_body = response_env[:body]
238
+ response_env[:body] =
239
+ case response_env[:response_headers]['Content-Encoding']
240
+ when 'gzip'
241
+ io = StringIO.new raw_body
242
+ Zlib::GzipReader.new(io, external_encoding: Encoding::UTF_8).read
243
+ when 'deflate'
244
+ Zlib::Inflate.inflate raw_body
245
+ else
246
+ raw_body
247
+ end
248
+ end
249
+ end
250
+ end
251
+
252
+ Faraday::Response.register_middleware fauna_decode: lambda { FaunaDecode }
253
+ end