yax-fauna 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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