setsuzoku 0.10.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitattributes +2 -0
- data/.gitignore +13 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +82 -0
- data/LICENSE.txt +21 -0
- data/README.md +93 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/setsuzoku.rb +37 -0
- data/lib/setsuzoku/api_response.rb +11 -0
- data/lib/setsuzoku/api_strategy.rb +124 -0
- data/lib/setsuzoku/auth_strategy.rb +72 -0
- data/lib/setsuzoku/credential.rb +37 -0
- data/lib/setsuzoku/exception.rb +18 -0
- data/lib/setsuzoku/external_api_handler.rb +19 -0
- data/lib/setsuzoku/pluggable.rb +87 -0
- data/lib/setsuzoku/plugin.rb +128 -0
- data/lib/setsuzoku/rspec.rb +2 -0
- data/lib/setsuzoku/rspec/dynamic_spec_helper.rb +281 -0
- data/lib/setsuzoku/service.rb +70 -0
- data/lib/setsuzoku/service/web_service.rb +21 -0
- data/lib/setsuzoku/service/web_service/api_strategies/rest_api_request.rb +17 -0
- data/lib/setsuzoku/service/web_service/api_strategies/rest_strategy.rb +155 -0
- data/lib/setsuzoku/service/web_service/api_strategy.rb +169 -0
- data/lib/setsuzoku/service/web_service/auth_strategies/basic_auth_strategy.rb +50 -0
- data/lib/setsuzoku/service/web_service/auth_strategies/o_auth_strategy.rb +173 -0
- data/lib/setsuzoku/service/web_service/auth_strategy.rb +48 -0
- data/lib/setsuzoku/service/web_service/credentials/basic_auth_credential.rb +52 -0
- data/lib/setsuzoku/service/web_service/credentials/o_auth_credential.rb +83 -0
- data/lib/setsuzoku/service/web_service/service.rb +31 -0
- data/lib/setsuzoku/utilities.rb +7 -0
- data/lib/setsuzoku/version.rb +6 -0
- data/setsuzoku.gemspec +50 -0
- data/sorbet/config +2 -0
- data/sorbet/rbi/gems/activesupport.rbi +1125 -0
- data/sorbet/rbi/gems/addressable.rbi +199 -0
- data/sorbet/rbi/gems/concurrent-ruby.rbi +1586 -0
- data/sorbet/rbi/gems/crack.rbi +62 -0
- data/sorbet/rbi/gems/faraday.rbi +615 -0
- data/sorbet/rbi/gems/hashdiff.rbi +66 -0
- data/sorbet/rbi/gems/httparty.rbi +401 -0
- data/sorbet/rbi/gems/i18n.rbi +133 -0
- data/sorbet/rbi/gems/mime-types-data.rbi +17 -0
- data/sorbet/rbi/gems/mime-types.rbi +218 -0
- data/sorbet/rbi/gems/multi_xml.rbi +35 -0
- data/sorbet/rbi/gems/multipart-post.rbi +53 -0
- data/sorbet/rbi/gems/nokogiri.rbi +1011 -0
- data/sorbet/rbi/gems/public_suffix.rbi +104 -0
- data/sorbet/rbi/gems/rake.rbi +646 -0
- data/sorbet/rbi/gems/rspec-core.rbi +1893 -0
- data/sorbet/rbi/gems/rspec-expectations.rbi +1123 -0
- data/sorbet/rbi/gems/rspec-mocks.rbi +1090 -0
- data/sorbet/rbi/gems/rspec-support.rbi +280 -0
- data/sorbet/rbi/gems/rspec.rbi +15 -0
- data/sorbet/rbi/gems/safe_yaml.rbi +124 -0
- data/sorbet/rbi/gems/thread_safe.rbi +82 -0
- data/sorbet/rbi/gems/tzinfo.rbi +406 -0
- data/sorbet/rbi/gems/webmock.rbi +532 -0
- data/sorbet/rbi/hidden-definitions/hidden.rbi +13722 -0
- data/sorbet/rbi/sorbet-typed/lib/activesupport/all/activesupport.rbi +1431 -0
- data/sorbet/rbi/sorbet-typed/lib/bundler/all/bundler.rbi +8684 -0
- data/sorbet/rbi/sorbet-typed/lib/httparty/all/httparty.rbi +427 -0
- data/sorbet/rbi/sorbet-typed/lib/minitest/all/minitest.rbi +108 -0
- data/sorbet/rbi/sorbet-typed/lib/ruby/all/open3.rbi +111 -0
- data/sorbet/rbi/sorbet-typed/lib/ruby/all/resolv.rbi +543 -0
- data/sorbet/rbi/todo.rbi +11 -0
- metadata +255 -0
@@ -0,0 +1,173 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Setsuzoku
|
5
|
+
module Service
|
6
|
+
module WebService
|
7
|
+
module AuthStrategies
|
8
|
+
# The API OAuth Authentication Interface definition.
|
9
|
+
# Any Plugin that implements this must implement all methods required for OAuth.
|
10
|
+
#
|
11
|
+
# Defines all necessary methods for handling authentication for any authentication strategy.
|
12
|
+
class OAuthStrategy < WebService::AuthStrategy
|
13
|
+
extend T::Sig
|
14
|
+
extend T::Helpers
|
15
|
+
|
16
|
+
def self.required_instance_methods
|
17
|
+
[]
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.credential_class
|
21
|
+
Setsuzoku::Service::WebService::Credentials::OAuthCredential
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.token_valid_for
|
25
|
+
24.hours
|
26
|
+
end
|
27
|
+
|
28
|
+
# Any api request headers that this service needs to set.
|
29
|
+
#
|
30
|
+
# @return [Hash]
|
31
|
+
sig { override.returns(T::Hash[Symbol, T.untyped]) }
|
32
|
+
def auth_headers
|
33
|
+
{
|
34
|
+
headers: {
|
35
|
+
'Authorization': "Bearer #{self.credential.token}"
|
36
|
+
}
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
# Get a new credential.
|
41
|
+
# Exchanges code for token, refresh_token and expires_on.
|
42
|
+
#
|
43
|
+
# @param args [Hash] the code from the initial auth response { code: 'abcdefg' }.
|
44
|
+
#
|
45
|
+
# @return void
|
46
|
+
sig { override.params(args: T.untyped).void }
|
47
|
+
def new_credential!(**args)
|
48
|
+
# get a token object based on the code retrieved from login
|
49
|
+
get_token!(params(grant_type: 'authorization_code',
|
50
|
+
code: args[:code]), :new_token)
|
51
|
+
end
|
52
|
+
|
53
|
+
# If the auth credentials are valid for this instance and auth_strategy.
|
54
|
+
#
|
55
|
+
# If the token is invalid we should refresh it. And verify that the credentials are now valid.
|
56
|
+
# Otherwise the credentials are already valid.
|
57
|
+
#
|
58
|
+
# @return [Boolean] true if the auth token is valid for the auth_strategy.
|
59
|
+
sig { override.returns(T::Boolean) }
|
60
|
+
def auth_credential_valid?
|
61
|
+
if token_is_invalid?
|
62
|
+
refresh_expired_token!
|
63
|
+
!token_is_invalid?
|
64
|
+
else
|
65
|
+
true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
# Determine whether the token is no longer valid.
|
72
|
+
#
|
73
|
+
# @return [Boolean] true if the token is invalid.
|
74
|
+
sig { returns(T::Boolean) }
|
75
|
+
def token_is_invalid?
|
76
|
+
active = self.credential.respond_to?(:"status") ? self.credential.status != 'disabled' : true
|
77
|
+
active && !self.credential.expires_on.blank? &&
|
78
|
+
!self.credential.refresh_token.blank? &&
|
79
|
+
(self.credential.expires_on < refresh_before_expiration_time)
|
80
|
+
end
|
81
|
+
|
82
|
+
sig { returns(DateTime) }
|
83
|
+
def refresh_before_expiration_time
|
84
|
+
45.minutes.from_now.to_datetime
|
85
|
+
end
|
86
|
+
|
87
|
+
# Exchange refresh_token for a new token and expires_on.
|
88
|
+
#
|
89
|
+
# @return [Boolean] true if the credential was refreshed successfully
|
90
|
+
sig { void }
|
91
|
+
def refresh_expired_token!
|
92
|
+
get_token!(params(grant_type: 'refresh_token',
|
93
|
+
refresh_token: self.credential.refresh_token), :refresh_token)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Exchange code for token, refresh_token and expires_on
|
97
|
+
#
|
98
|
+
# @return void
|
99
|
+
sig { params(code: String, redirect_url: String).void }
|
100
|
+
def custom_token!(code: nil, redirect_url: nil)
|
101
|
+
get_token!(params(grant_type: 'authorization_code',
|
102
|
+
code: code,
|
103
|
+
redirect_uri: redirect_url), :refresh_token)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Exchange code for a new token via POST request to API token url,
|
107
|
+
# and set token, expiry, and status on the integration
|
108
|
+
#
|
109
|
+
# @param [Hash] body the request body for the token POST request
|
110
|
+
#
|
111
|
+
# @return void
|
112
|
+
sig { params(body: T::Hash[Symbol, String], action: Symbol).void }
|
113
|
+
def get_token!(body, action)
|
114
|
+
success = false
|
115
|
+
request = self.api_strategy.request_class.new(action: action, body: body)
|
116
|
+
|
117
|
+
resp = self.api_strategy.call_external_api(request: request, strategy: :auth)
|
118
|
+
|
119
|
+
if resp.data && resp.data[:access_token]
|
120
|
+
self.credential.status = 'active' if self.credential.respond_to?(:"status=")
|
121
|
+
self.credential.token = resp.data[:access_token]
|
122
|
+
self.credential.refresh_token = resp.data[:refresh_token] if resp.data.key?(:refresh_token)
|
123
|
+
self.credential.expires_on = if resp.data[:expires_in]
|
124
|
+
resp.data[:expires_in].to_i.seconds.from_now
|
125
|
+
# elsif resp.data[:issued_at] && self.class.token_valid_for
|
126
|
+
# Time.at(resp.data[:issued_at].to_i / 1000) + self.class.token_valid_for
|
127
|
+
end
|
128
|
+
|
129
|
+
self.plugin.set_credential_fields!(resp) if self.plugin.respond_to?(:set_credential_fields!)
|
130
|
+
|
131
|
+
#TODO: figure out a better way to do this when we add other integrations...
|
132
|
+
#
|
133
|
+
# if self.is_a?(FacebookIntegration)
|
134
|
+
# resp = self.exchange_for_long_lived_token
|
135
|
+
# if resp && resp.data['access_token']
|
136
|
+
# self.token = resp.data['access_token']
|
137
|
+
# self.refresh_token = resp.data['access_token']
|
138
|
+
# self.expires_on = 59.days.from_now
|
139
|
+
# end
|
140
|
+
# end
|
141
|
+
else
|
142
|
+
self.credential.status = 'error' if self.credential.respond_to?(:"status=")
|
143
|
+
end
|
144
|
+
|
145
|
+
if self.credential.respond_to?(:"save")
|
146
|
+
self.credential.save && resp.success
|
147
|
+
else
|
148
|
+
resp.success
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# Add some default params to the params hash.
|
153
|
+
#
|
154
|
+
# @param params [Hash] the original params hash.
|
155
|
+
#
|
156
|
+
# @return [Hash] the merged params hash.
|
157
|
+
sig { params(params: T::Hash[T.untyped, T.untyped]).returns(T::Hash[T.untyped, T.untyped]) }
|
158
|
+
def params(params)
|
159
|
+
if params.key?(:redirect_uri)
|
160
|
+
params.merge(client_id: self.credential.client_id,
|
161
|
+
client_secret: self.credential.client_secret)
|
162
|
+
else
|
163
|
+
params.merge(client_id: self.credential.client_id,
|
164
|
+
client_secret: self.credential.client_secret,
|
165
|
+
redirect_uri: self.credential.redirect_url_override.nil? ? self.credential.redirect_url : self.credential.redirect_url_override)
|
166
|
+
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Setsuzoku
|
5
|
+
module Service
|
6
|
+
# The Token-based API Authentication Interface definition.
|
7
|
+
# Any Plugin that implements this must implement all methods defined here.
|
8
|
+
#
|
9
|
+
# Defines all necessary methods for handling authentication for any token-based authentication.
|
10
|
+
module WebService
|
11
|
+
|
12
|
+
class AuthStrategy
|
13
|
+
include Setsuzoku::AuthStrategy
|
14
|
+
extend T::Sig
|
15
|
+
extend T::Helpers
|
16
|
+
abstract!
|
17
|
+
|
18
|
+
# The authorization headers that need to be defined for this authentication strategy.
|
19
|
+
#
|
20
|
+
# @return [Hash(String)] the authorization key/values needed for authentication.
|
21
|
+
sig { abstract.returns(T::Hash[Symbol, T.untyped]) }
|
22
|
+
def auth_headers;end
|
23
|
+
|
24
|
+
# These are interface methods that a plugin that implements this strategy must implement.
|
25
|
+
module InterfaceMethods
|
26
|
+
extend T::Sig
|
27
|
+
extend T::Helpers
|
28
|
+
abstract!
|
29
|
+
|
30
|
+
# All auth actions that are implemented.
|
31
|
+
#
|
32
|
+
# @return [Hash] all auth endpoint definitions for the API.
|
33
|
+
sig { abstract.returns(T::Hash[T.untyped, T.untyped]) }
|
34
|
+
def auth_actions; end
|
35
|
+
|
36
|
+
# The base auth url for the plugin.
|
37
|
+
#
|
38
|
+
# @return [String] the auth url.
|
39
|
+
sig { overridable.returns(String) }
|
40
|
+
def auth_base_url
|
41
|
+
self.plugin.api_base_url
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Setsuzoku
|
5
|
+
module Service
|
6
|
+
module WebService
|
7
|
+
module Credentials
|
8
|
+
module BasicAuthCredential
|
9
|
+
include Setsuzoku::Credential
|
10
|
+
extend T::Sig
|
11
|
+
extend T::Helpers
|
12
|
+
abstract!
|
13
|
+
|
14
|
+
# The username to use for the credential.
|
15
|
+
#
|
16
|
+
# @return [String] the credential's token.
|
17
|
+
sig{ abstract.returns(T.nilable(String)) }
|
18
|
+
def username; end
|
19
|
+
|
20
|
+
# The username to set for the credential.
|
21
|
+
#
|
22
|
+
# @return [String] the credential's token to set.
|
23
|
+
#
|
24
|
+
sig{ abstract.params(val: String).returns(T.nilable(String)) }
|
25
|
+
def username=(val); end
|
26
|
+
|
27
|
+
# The password to use for the credential.
|
28
|
+
#
|
29
|
+
# @return [String] the credential's token.
|
30
|
+
sig{ abstract.returns(T.nilable(String)) }
|
31
|
+
def password; end
|
32
|
+
|
33
|
+
# The password to set for the credential.
|
34
|
+
#
|
35
|
+
# @return [String] the credential's token to set.
|
36
|
+
#
|
37
|
+
sig{ abstract.params(val: String).returns(T.nilable(String)) }
|
38
|
+
def password=(val); end
|
39
|
+
|
40
|
+
# Stub a basic_auth_credential-like instance.
|
41
|
+
#
|
42
|
+
# @return [Struct] a stubbed basic_auth_credential-like struct.
|
43
|
+
sig { returns(Struct) }
|
44
|
+
def self.stub_credential
|
45
|
+
s = Struct.new(:username, :password)
|
46
|
+
s.new('stubbed_username', 'stubbed_password')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'active_support/core_ext/numeric/time'
|
5
|
+
|
6
|
+
module Setsuzoku
|
7
|
+
module Service
|
8
|
+
module WebService
|
9
|
+
module Credentials
|
10
|
+
module OAuthCredential
|
11
|
+
extend T::Sig
|
12
|
+
extend T::Helpers
|
13
|
+
abstract!
|
14
|
+
|
15
|
+
# The application's client_id to o_auth with.
|
16
|
+
#
|
17
|
+
# @return [String] the client_id for o_auth.
|
18
|
+
sig { abstract.returns(T.nilable(String)) }
|
19
|
+
def client_id; end
|
20
|
+
|
21
|
+
# The application's client_secret to o_auth with.
|
22
|
+
#
|
23
|
+
# @return [String] the client_secret for o_auth.
|
24
|
+
sig { abstract.returns(T.nilable(String)) }
|
25
|
+
def client_secret; end
|
26
|
+
|
27
|
+
# The application's redirect url to handle an o_auth redirect
|
28
|
+
#
|
29
|
+
# @return [String] the redirect url.
|
30
|
+
sig { abstract.returns(T.nilable(String)) }
|
31
|
+
def redirect_url; end
|
32
|
+
|
33
|
+
# The token to use for the credential.
|
34
|
+
#
|
35
|
+
# @return [String] the credential's token.
|
36
|
+
sig{ abstract.returns(T.nilable(String)) }
|
37
|
+
def token; end
|
38
|
+
|
39
|
+
# The token to set for the credential.
|
40
|
+
#
|
41
|
+
# @return [String] the credential's token to set.
|
42
|
+
#
|
43
|
+
sig{ abstract.params(val: String).returns(T.nilable(String)) }
|
44
|
+
def token=(val); end
|
45
|
+
|
46
|
+
# The refresh token to use for the credential.
|
47
|
+
#
|
48
|
+
# @return [String] the credential's refresh token.
|
49
|
+
sig{ abstract.returns(T.nilable(String)) }
|
50
|
+
def refresh_token; end
|
51
|
+
|
52
|
+
# The refresh token to set for the credential.
|
53
|
+
#
|
54
|
+
# @return [String] the credential's refresh token to set.
|
55
|
+
#
|
56
|
+
sig{ abstract.params(val: String).returns(T.nilable(String)) }
|
57
|
+
def refresh_token=(val); end
|
58
|
+
|
59
|
+
# The time the currently valid token expires on.
|
60
|
+
#
|
61
|
+
# @return [Datetime] the time the current token expires.
|
62
|
+
sig{ abstract.returns(T.nilable(DateTime)) }
|
63
|
+
def expires_on; end
|
64
|
+
|
65
|
+
# The time to set for when the token expires on.
|
66
|
+
#
|
67
|
+
# @return [Datetime] the time to set for the current token's expiry.
|
68
|
+
sig{ abstract.params(val: DateTime).returns(T.nilable(DateTime)) }
|
69
|
+
def expires_on=(val); end
|
70
|
+
|
71
|
+
# Stub an o_auth_credential-like instance.
|
72
|
+
#
|
73
|
+
# @return [Struct] a stubbed o_auth_credential-like struct.
|
74
|
+
sig { returns(Struct) }
|
75
|
+
def self.stub_credential
|
76
|
+
s = Struct.new(:client_id, :client_secret, :redirect_url, :token, :refresh_token, :expires_on, :settings)
|
77
|
+
s.new('stubbed_client_id', 'stubbed_client_secret', 'stubbed_redirect_url', 'stubbed_token', 'refresh_token', (Time.now + 30.days), 'extension': 'test')
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module Setsuzoku
|
5
|
+
module Service
|
6
|
+
module WebService
|
7
|
+
# WebService's Service should define all available auth and api strategies.
|
8
|
+
class Service
|
9
|
+
extend T::Sig
|
10
|
+
extend T::Helpers
|
11
|
+
include Setsuzoku::Service
|
12
|
+
|
13
|
+
# The api and auth strategies available for WebService.
|
14
|
+
#
|
15
|
+
# @return [Hash(Hash(Class))] the available_strategies object for WebService.
|
16
|
+
sig { override.returns(T::Hash[Symbol, T::Hash[Symbol, Class]]) }
|
17
|
+
def self.available_strategies
|
18
|
+
{
|
19
|
+
auth: {
|
20
|
+
basic: Setsuzoku::Service::WebService::AuthStrategies::BasicAuthStrategy,
|
21
|
+
o_auth: Setsuzoku::Service::WebService::AuthStrategies::OAuthStrategy
|
22
|
+
},
|
23
|
+
api: {
|
24
|
+
rest: ApiStrategies::RestStrategy
|
25
|
+
}
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/setsuzoku.gemspec
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "setsuzoku/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'setsuzoku'
|
8
|
+
spec.version = Setsuzoku::VERSION
|
9
|
+
spec.authors = ['Luke Stadtler']
|
10
|
+
spec.email = ['luke@rocketreferrals.com']
|
11
|
+
spec.homepage = 'https://github.com/rocketreferrals/setsuzoku'
|
12
|
+
spec.summary = 'Extensible 3rd-party interface and functionality plugins'
|
13
|
+
spec.description = 'Easily build generic, reusable 3rd party SDK-like plugins (intended to share).
|
14
|
+
Future functionality will include dynamic UIs and other functionality around the plugin.'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
18
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
19
|
+
# if spec.respond_to?(:metadata)
|
20
|
+
# spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
|
21
|
+
#
|
22
|
+
# spec.metadata["homepage_uri"] = spec.homepage
|
23
|
+
# spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
|
24
|
+
# spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
25
|
+
# else
|
26
|
+
# raise "RubyGems 2.0 or newer is required to protect against " \
|
27
|
+
# "public gem pushes."
|
28
|
+
# end
|
29
|
+
|
30
|
+
# Specify which files should be added to the gem when it is released.
|
31
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
32
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
33
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
34
|
+
end
|
35
|
+
spec.bindir = "exe"
|
36
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
37
|
+
spec.require_paths = ["lib"]
|
38
|
+
|
39
|
+
spec.add_development_dependency "bundler", "~> 1.17"
|
40
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
41
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
42
|
+
spec.add_development_dependency "webmock", "~> 3.8"
|
43
|
+
spec.add_runtime_dependency "activesupport", "~> 5.0"
|
44
|
+
spec.add_development_dependency "sorbet", "~> 0.5"
|
45
|
+
spec.add_runtime_dependency "sorbet-runtime", "~> 0.5"
|
46
|
+
#TODO: we should remove httparty if we can just use faraday
|
47
|
+
spec.add_runtime_dependency "httparty", "~> 0.16.4"
|
48
|
+
spec.add_runtime_dependency "faraday", "~> 0.11"
|
49
|
+
spec.add_runtime_dependency "nokogiri", "~> 1.10"
|
50
|
+
end
|