agx 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 12a614baa601cb06ea43c79debbe22c3796dfe86
4
+ data.tar.gz: 8e9c959807c63150179794206fa24fc81cbb276b
5
+ SHA512:
6
+ metadata.gz: ee30307fc2cb28199560bfa331f984ec3513142fe048422f3941b653a4f470464e0e185c4a4e5cd48717ce0603c5f334f780b9d46c1b48cf58788ffa5fc97aae
7
+ data.tar.gz: 24e24fbfa71a88b00b264a4b99d0a26161d481ccfce929ea247da8a5e6476870eb5fc8f8aade2e9670347432944cdc03276c68d606b1b46e1aede10b0ce436a7
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.1
5
+ before_install: gem install bundler -v 1.12.5
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Required for allowing Client Credentials w/ Bearer auth instead of Basic
4
+ # See: https://github.com/intridea/oauth2/pull/252
5
+ gem 'oauth2', github: 'CropQuest/oauth2', branch: 'client_credentials_header'
6
+
7
+ # Specify your gem's dependencies in agx.gemspec
8
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2016 Crop Quest, Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,117 @@
1
+ # agX Platform API Client
2
+
3
+ [![Gem Version](http://img.shields.io/gem/v/agx.svg)][gem]
4
+
5
+ [gem]: https://rubygems.org/gems/agx
6
+
7
+ Ruby client for accessing SST Software's [agX Platform APIs](http://www.agxplatform.com/agx-apis/).
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'agx'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install agx
24
+
25
+ ## Usage
26
+
27
+ ### agX Content API
28
+
29
+ Setup agX Content Client (OAuth 2 Client Credentials Flow)
30
+ ```ruby
31
+ @agx_content_client = Agx::Content::Client.new(
32
+ client_id: "your_client_id",
33
+ client_secret: "your_client_secret",
34
+ site: "content-api-endpoint-url", # optional
35
+ token_url: "auth-token-endpoint-url", # optional
36
+ version: "v1" # optional
37
+ )
38
+ ```
39
+
40
+ Make get requests for Content API resources
41
+ ```ruby
42
+ # @agx_content_client.get("ResourceName", params_hash)
43
+ # => 'parsed_json_response_body'
44
+
45
+ crops = @agx_content_client.get("Crop")
46
+
47
+ # Passing in publishDate as param
48
+ weeds = @agx_content_client.get("Weed", {publishDate: date.to_s})
49
+ ```
50
+
51
+ ### agX Sync API
52
+
53
+ Setup agX Sync Client (OAuth 2 Authorization Code Flow)
54
+
55
+ ***This requires that you have already previously authenticated and authorized
56
+ a user to agX through the authorization code grant flow process and have
57
+ persisted their sync ID, access token, refresh token, and access token
58
+ expiration timestamp.***
59
+
60
+ ```ruby
61
+ @agx_sync_client = Agx::Sync::Client.new(
62
+ client_id: "your_client_id",
63
+ client_secret: "your_client_secret",
64
+ site: "sync-api-endpoint-url", # optional
65
+ host: "sync-api-endpoint-without-protocol", # optional
66
+ authorize_url: "authorize-endpoint-url", # optional
67
+ token_url: "auth-token-endpoint-url", # optional
68
+ version: "v3", # optional
69
+ sync_id: "agx_user_sync_id",
70
+ access_token: "agx_user_agx_token",
71
+ refresh_token: "agx_user_refresh_token",
72
+ token_expires_at: "access_token_expiration_timestamp",
73
+ transaction_id: "agx_user_previous_transaction_id" # optional
74
+ )
75
+ ```
76
+
77
+ Initiate a sync transaction, make Sync API requests, and end transaction
78
+
79
+ ***Currently only get requests are supported***
80
+ ```ruby
81
+ # @agx_sync_client.get("Resource", start_time)
82
+ # => 'parsed_json_response_body'
83
+
84
+ # You should persist transaction ID per user until transaction is successfully
85
+ # ended by call to end_transaction
86
+ transaction_id = @agx_sync_client.start_transaction
87
+
88
+ growers = @agx_sync_client.get("Grower")
89
+
90
+ # Get all farms accessible for a grower
91
+ farms = @agx_sync_client.get("Grower/#{grower.guid}/Farm")
92
+
93
+ # Get all server changes on farms accessible for a grower since start_time
94
+ farms = @agx_sync_client.get("Grower/#{grower.guid}/Farm", last_sync_date.to_s)
95
+
96
+ # etc...
97
+
98
+ @agx_sync_client.end_transaction
99
+
100
+ # clear the persisted transaction ID for user after ending sync transaction
101
+ user_transaction_id = nil
102
+ ```
103
+
104
+ ## Development
105
+
106
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. To install this gem onto your local machine, run `bundle exec rake install`.
107
+
108
+ ## Contributing
109
+
110
+ Bug reports and pull requests are welcome on GitHub at https://github.com/CropQuest/agx-ruby.
111
+
112
+
113
+ ## Copyright
114
+
115
+ Copyright (c) 2016 [Crop Quest, Inc.](http://www.cropquest.com) See LICENSE.txt for details.
116
+
117
+ [agX](http://www.agxplatform.com/) is a registered trademark of [SST Software](http://www.sstsoftware.com/).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/agx.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'agx/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "agx"
8
+ spec.version = Agx::VERSION
9
+ spec.authors = ["Bryce Johnston"]
10
+ spec.email = ["bjohnston@cropquest.com"]
11
+
12
+ spec.summary = %q{Ruby client for accessing agX Platform APIs.}
13
+ spec.description = %q{Ruby client for accessing SST Software's agX Platform APIs.}
14
+ spec.homepage = "https://github.com/CropQuest/agx-ruby"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_dependency "oj", "~> 2.17.1"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.12"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rspec", "~> 3.0"
27
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "agx"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,126 @@
1
+ module Agx
2
+ module Content
3
+ class Client
4
+ attr_accessor :client_id, :client_secret, :site, :token_url, :version
5
+
6
+ def initialize(client_id: nil, client_secret: nil, site: nil, token_url: nil, version: nil)
7
+ @client_id = client_id || ENV['AGX_CONTENT_CLIENT_ID']
8
+ @client_secret = client_secret || ENV['AGX_CONTENT_CLIENT_SECRET']
9
+ @site = site || "https://refdata.agxplatform.com"
10
+ @token_url = token_url || "https://auth.agxplatform.com/Account/Token"
11
+ @version = version || "v1"
12
+ @client = set_client
13
+ @token = {
14
+ access_token: nil,
15
+ expires_at: nil
16
+ }
17
+ end
18
+
19
+ def get(resource, params = {})
20
+ validate_credentials
21
+
22
+ resource = "/api/#{@version}/#{resource}"
23
+ begin
24
+ response = current_token.get(resource, {:headers => { "oauth-scopes" => "referencedata" }, :params => params})
25
+ parse_response(response.body)
26
+ rescue => e
27
+ handle_error(e)
28
+ end
29
+ end
30
+
31
+ protected
32
+
33
+ def validate_credentials
34
+ unless @client_id && @client_secret
35
+ error = Agx::Error.new("agX Client Credentials Not Set", {title: "AGX_CREDENTIALS_ERROR"})
36
+ raise error
37
+ end
38
+ end
39
+
40
+ def parse_response(response_body)
41
+ parsed_response = nil
42
+
43
+ if response_body && !response_body.empty?
44
+ begin
45
+ parsed_response = Oj.load(response_body)
46
+ rescue Oj::ParseError
47
+ error = Agx::Error.new("Unparseable response: #{response_body}")
48
+ error.title = "UNPARSEABLE_RESPONSE"
49
+ error.status_code = 500
50
+ raise error
51
+ end
52
+ end
53
+
54
+ parsed_response
55
+ end
56
+
57
+ def handle_error(error)
58
+ error_params = {}
59
+
60
+ begin
61
+ if error.is_a?(OAuth2::Error) && error.response
62
+ error_params[:title] = "HTTP_#{error.response.status}_ERROR"
63
+ error_params[:status_code] = error.response.status
64
+ error_params[:raw_body] = error.response.body
65
+ error_params[:body] = Oj.load(error.response.body)
66
+ elsif error.is_a?(Errno::ETIMEDOUT)
67
+ error_params[:title] = "TIMEOUT_ERROR"
68
+ end
69
+ rescue Oj::ParseError
70
+ end
71
+
72
+ error_to_raise = Agx::Error.new(error.message, error_params)
73
+ raise error_to_raise
74
+ end
75
+
76
+ def current_token
77
+ if @token[:access_token].nil? || @token[:expires_at].nil?
78
+ new_token = api_token
79
+ else
80
+ oauth_token = OAuth2::AccessToken.new(
81
+ @client,
82
+ @token[:access_token],
83
+ {expires_at: @token[:expires_at]}
84
+ )
85
+ if Time.now.to_i + 180 >= @token[:expires_at] || oauth_token.expired?
86
+ new_token = api_token
87
+ else
88
+ new_token = oauth_token
89
+ end
90
+ end
91
+
92
+ new_token
93
+ end
94
+
95
+ def api_token
96
+ begin
97
+ new_token = @client.client_credentials.get_token(
98
+ {
99
+ 'client_id' => @client_id,
100
+ 'client_secret' => @client_secret,
101
+ 'scope' => "referencedata"
102
+ },
103
+ { :header_format => 'Bearer' }
104
+ )
105
+ rescue => e
106
+ handle_error(e)
107
+ end
108
+
109
+ @token[:access_token] = new_token.token
110
+ @token[:expires_at] = new_token.expires_at
111
+
112
+ OAuth2::AccessToken.new @client, new_token.token
113
+ end
114
+
115
+ def set_client
116
+ @client = OAuth2::Client.new(
117
+ @client_id,
118
+ @client_secret,
119
+ site: @site,
120
+ token_url: @token_url
121
+ )
122
+ end
123
+
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,6 @@
1
+ require "agx/content/client"
2
+
3
+ module Agx
4
+ module Content
5
+ end
6
+ end
data/lib/agx/error.rb ADDED
@@ -0,0 +1,29 @@
1
+ module Agx
2
+ class Error < StandardError
3
+ attr_reader :title, :detail, :body, :raw_body, :status_code
4
+
5
+ def initialize(message = "", params = {})
6
+ @title = params[:title]
7
+ @detail = message
8
+ @body = params[:body]
9
+ @raw_body = params[:raw_body]
10
+ @status_code = params[:status_code]
11
+
12
+ super(message)
13
+ end
14
+
15
+ def to_s
16
+ super + " " + instance_variables_to_s
17
+ end
18
+
19
+ private
20
+
21
+ def instance_variables_to_s
22
+ [:title, :detail, :body, :raw_body, :status_code].map do |attr|
23
+ attr_value = send(attr)
24
+
25
+ "@#{attr}=#{attr_value.inspect}"
26
+ end.join(", ")
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,169 @@
1
+ module Agx
2
+ module Sync
3
+ class Client
4
+ attr_accessor :client_id, :client_secret, :site, :host, :authorize_url,
5
+ :token_url, :version, :sync_id, :access_token, :refresh_token, :token_expires_at,
6
+ :transaction_id
7
+
8
+ def initialize(client_id: nil, client_secret: nil, site: nil, host: nil,
9
+ authorize_url: nil, token_url: nil, version: nil, sync_id: nil,
10
+ access_token: nil, refresh_token: nil, token_expires_at: nil,
11
+ transaction_id: nil)
12
+ @client_id = client_id || ENV['AGX_SYNC_CLIENT_ID']
13
+ @client_secret = client_secret || ENV['AGX_SYNC_CLIENT_SECRET']
14
+ @site = site || "https://sync.agxplatform.com"
15
+ @host = host || "sync.agxplatform.com"
16
+ @authorize_url = authorize_url || "https://auth.agxplatform.com/Account/Authorize"
17
+ @token_url = token_url || "https://auth.agxplatform.com/Account/Token"
18
+ @version = version || "v3"
19
+ @sync_id = sync_id
20
+ @api_url = "#{@site}/api/#{@version}/Account/#{@sync_id}/"
21
+ @headers = {
22
+ 'Content-Type' => "application/json",
23
+ 'Accept' => "application/json",
24
+ 'oauth-scopes' => "Sync",
25
+ 'Host' => @host
26
+ }
27
+ @client = set_client
28
+ @token = {
29
+ access_token: access_token,
30
+ refresh_token: refresh_token,
31
+ expires_at: token_expires_at
32
+ }
33
+ @transaction_id = transaction_id
34
+ end
35
+
36
+ def get(resource, start_time = nil)
37
+ validate_sync_attributes
38
+
39
+ url = "#{@api_url}#{resource}?transactionId=#{@transaction_id}"
40
+ if !start_time.nil?
41
+ url = "#{@api_url}#{resource}?startTime=#{start_time}&transactionId=#{@transaction_id}"
42
+ end
43
+
44
+ begin
45
+ response = current_token.get(url, :headers => @headers)
46
+ parse_response(response.body)
47
+ rescue => e
48
+ handle_error(e)
49
+ end
50
+ end
51
+
52
+ def start_transaction
53
+ validate_credentials
54
+
55
+ if !@transaction_id.nil?
56
+ end_transaction
57
+ end
58
+ begin
59
+ transaction_request = current_token.get(
60
+ "#{@api_url}Transaction",
61
+ :headers => @headers
62
+ )
63
+ @transaction_id = Oj.load(transaction_request.body)
64
+ rescue => e
65
+ handle_error(e)
66
+ end
67
+
68
+ @transaction_id
69
+ end
70
+
71
+ def end_transaction
72
+ validate_credentials
73
+
74
+ begin
75
+ end_transaction_request = current_token.delete(
76
+ "#{@api_url}Transaction/#{@transaction_id}",
77
+ :headers => @headers
78
+ )
79
+ rescue => e
80
+ handle_error(e)
81
+ end
82
+ end
83
+
84
+ protected
85
+
86
+ def validate_credentials
87
+ unless @client_id && @client_secret
88
+ error = Agx::Error.new("agX Client Credentials Not Set", {title: "AGX_CREDENTIALS_ERROR"})
89
+ raise error
90
+ end
91
+ end
92
+
93
+ def validate_sync_attributes
94
+ validate_credentials
95
+
96
+ unless @sync_id && @transaction_id
97
+ error = Agx::Error.new("agX Sync Transaction Attributes Not Set", {title: "AGX_SYNC_ATTRIBUTES_ERROR"})
98
+ raise error
99
+ end
100
+ end
101
+
102
+ def parse_response(response_body)
103
+ parsed_response = nil
104
+
105
+ if response_body && !response_body.empty?
106
+ begin
107
+ parsed_response = Oj.load(response_body)
108
+ rescue Oj::ParseError
109
+ error = Agx::Error.new("Unparseable response: #{response_body}")
110
+ error.title = "UNPARSEABLE_RESPONSE"
111
+ error.status_code = 500
112
+ raise error
113
+ end
114
+ end
115
+
116
+ parsed_response
117
+ end
118
+
119
+ def handle_error(error)
120
+ error_params = {}
121
+
122
+ begin
123
+ if error.is_a?(OAuth2::Error) && error.response
124
+ error_params[:title] = "HTTP_#{error.response.status}_ERROR"
125
+ error_params[:status_code] = error.response.status
126
+ error_params[:raw_body] = error.response.body
127
+ error_params[:body] = Oj.load(error.response.body)
128
+ elsif error.is_a?(Errno::ETIMEDOUT)
129
+ error_params[:title] = "TIMEOUT_ERROR"
130
+ end
131
+ rescue Oj::ParseError
132
+ end
133
+
134
+ error_to_raise = Agx::Error.new(error.message, error_params)
135
+ raise error_to_raise
136
+ end
137
+
138
+ def current_token
139
+ new_token = OAuth2::AccessToken.new @client, @token[:access_token], {
140
+ expires_at: @token[:expires_at],
141
+ refresh_token: @token[:refresh_token]
142
+ }
143
+ if Time.now.to_i + 90 >= @token[:expires_at]
144
+ new_token = new_token.refresh!
145
+ @token[:access_token] = new_token.token
146
+ @token[:refresh_token] = new_token.refresh_token
147
+ @token[:expires_at] = new_token.expires_at
148
+ end
149
+
150
+ new_token
151
+ end
152
+
153
+ def set_client
154
+ @client = OAuth2::Client.new(
155
+ @client_id,
156
+ @client_secret, {
157
+ site: @site,
158
+ authorize_url: @authorize_url,
159
+ token_url: @token_url,
160
+ options: {
161
+ ssl: { ca_path: "/usr/lib/ssl/certs" }
162
+ }
163
+ }
164
+ )
165
+ end
166
+
167
+ end
168
+ end
169
+ end
data/lib/agx/sync.rb ADDED
@@ -0,0 +1,6 @@
1
+ require "agx/sync/client"
2
+
3
+ module Agx
4
+ module Sync
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ module Agx
2
+ VERSION = "0.1.0"
3
+ end
data/lib/agx.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'oauth2'
2
+ require 'oj'
3
+
4
+ require "agx/version"
5
+ require "agx/error"
6
+ require "agx/content"
7
+ require "agx/sync"
8
+
9
+ module Agx
10
+ end
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: agx
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Bryce Johnston
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-09-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: oj
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.17.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.17.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.12'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.12'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ description: Ruby client for accessing SST Software's agX Platform APIs.
70
+ email:
71
+ - bjohnston@cropquest.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - ".travis.yml"
79
+ - Gemfile
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - agx.gemspec
84
+ - bin/console
85
+ - bin/setup
86
+ - lib/agx.rb
87
+ - lib/agx/content.rb
88
+ - lib/agx/content/client.rb
89
+ - lib/agx/error.rb
90
+ - lib/agx/sync.rb
91
+ - lib/agx/sync/client.rb
92
+ - lib/agx/version.rb
93
+ homepage: https://github.com/CropQuest/agx-ruby
94
+ licenses:
95
+ - MIT
96
+ metadata: {}
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubyforge_project:
113
+ rubygems_version: 2.6.4
114
+ signing_key:
115
+ specification_version: 4
116
+ summary: Ruby client for accessing agX Platform APIs.
117
+ test_files: []
118
+ has_rdoc: