restforce 4.2.1 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/unhandled-salesforce-error.md +17 -0
  3. data/.github/dependabot.yml +10 -0
  4. data/.github/funding.yml +1 -0
  5. data/.github/workflows/build.yml +23 -0
  6. data/.github/workflows/faraday.yml +27 -0
  7. data/.rubocop.yml +5 -4
  8. data/CHANGELOG.md +115 -0
  9. data/CONTRIBUTING.md +21 -1
  10. data/Dockerfile +31 -0
  11. data/Gemfile +15 -7
  12. data/README.md +102 -24
  13. data/UPGRADING.md +67 -0
  14. data/docker-compose.yml +7 -0
  15. data/lib/restforce/abstract_client.rb +1 -0
  16. data/lib/restforce/collection.rb +27 -4
  17. data/lib/restforce/concerns/api.rb +3 -2
  18. data/lib/restforce/concerns/base.rb +2 -2
  19. data/lib/restforce/concerns/caching.rb +7 -0
  20. data/lib/restforce/concerns/composite_api.rb +104 -0
  21. data/lib/restforce/concerns/connection.rb +1 -1
  22. data/lib/restforce/concerns/picklists.rb +2 -2
  23. data/lib/restforce/concerns/streaming.rb +1 -3
  24. data/lib/restforce/config.rb +14 -9
  25. data/lib/restforce/error_code.rb +650 -0
  26. data/lib/restforce/file_part.rb +32 -0
  27. data/lib/restforce/mash.rb +8 -3
  28. data/lib/restforce/middleware/authentication.rb +1 -0
  29. data/lib/restforce/middleware/caching.rb +140 -15
  30. data/lib/restforce/middleware/json_request.rb +90 -0
  31. data/lib/restforce/middleware/json_response.rb +85 -0
  32. data/lib/restforce/middleware/logger.rb +14 -9
  33. data/lib/restforce/middleware/raise_error.rb +13 -5
  34. data/lib/restforce/middleware.rb +2 -0
  35. data/lib/restforce/version.rb +1 -1
  36. data/lib/restforce.rb +15 -14
  37. data/restforce.gemspec +13 -21
  38. data/spec/fixtures/sobject/list_view_results_success_response.json +151 -0
  39. data/spec/integration/abstract_client_spec.rb +56 -35
  40. data/spec/integration/data/client_spec.rb +6 -2
  41. data/spec/spec_helper.rb +24 -1
  42. data/spec/support/client_integration.rb +7 -7
  43. data/spec/support/concerns.rb +1 -1
  44. data/spec/support/fixture_helpers.rb +1 -3
  45. data/spec/support/middleware.rb +1 -2
  46. data/spec/unit/collection_spec.rb +38 -2
  47. data/spec/unit/concerns/api_spec.rb +22 -15
  48. data/spec/unit/concerns/authentication_spec.rb +6 -6
  49. data/spec/unit/concerns/caching_spec.rb +26 -0
  50. data/spec/unit/concerns/composite_api_spec.rb +143 -0
  51. data/spec/unit/concerns/connection_spec.rb +2 -2
  52. data/spec/unit/concerns/streaming_spec.rb +4 -4
  53. data/spec/unit/config_spec.rb +2 -2
  54. data/spec/unit/error_code_spec.rb +61 -0
  55. data/spec/unit/mash_spec.rb +5 -0
  56. data/spec/unit/middleware/authentication/jwt_bearer_spec.rb +24 -8
  57. data/spec/unit/middleware/authentication/password_spec.rb +12 -4
  58. data/spec/unit/middleware/authentication/token_spec.rb +12 -4
  59. data/spec/unit/middleware/authentication_spec.rb +14 -8
  60. data/spec/unit/middleware/gzip_spec.rb +2 -2
  61. data/spec/unit/middleware/raise_error_spec.rb +29 -10
  62. data/spec/unit/signed_request_spec.rb +1 -1
  63. metadata +64 -187
  64. data/.circleci/config.yml +0 -56
  65. data/lib/restforce/upload_io.rb +0 -9
@@ -11,9 +11,10 @@ module Restforce
11
11
  # appropriate Restforce::Collection, Restforce::SObject and
12
12
  # Restforce::Mash objects.
13
13
  def build(val, client)
14
- if val.is_a?(Array)
14
+ case val
15
+ when Array
15
16
  val.collect { |a_val| self.build(a_val, client) }
16
- elsif val.is_a?(Hash)
17
+ when Hash
17
18
  self.klass(val).new(val, client)
18
19
  else
19
20
  val
@@ -28,7 +29,7 @@ module Restforce
28
29
  # of sobject records.
29
30
  Restforce::Collection
30
31
  elsif val.key? 'attributes'
31
- case (val['attributes']['type'])
32
+ case val.dig('attributes', 'type')
32
33
  when "Attachment"
33
34
  Restforce::Attachment
34
35
  when "Document"
@@ -55,6 +56,9 @@ module Restforce
55
56
  self.class.new(self, @client, self.default)
56
57
  end
57
58
 
59
+ # The #convert_value method and its signature are part of Hashie::Mash's API, so we
60
+ # can't unilaterally decide to change `duping` to be a keyword argument
61
+ # rubocop:disable Style/OptionalBooleanParameter
58
62
  def convert_value(val, duping = false)
59
63
  case val
60
64
  when self.class
@@ -68,5 +72,6 @@ module Restforce
68
72
  val
69
73
  end
70
74
  end
75
+ # rubocop:enable Style/OptionalBooleanParameter
71
76
  end
72
77
  end
@@ -49,6 +49,7 @@ module Restforce
49
49
  @connection ||= Faraday.new(faraday_options) do |builder|
50
50
  builder.use Faraday::Request::UrlEncoded
51
51
  builder.use Restforce::Middleware::Mashify, nil, @options
52
+ builder.use Faraday::FollowRedirects::Middleware
52
53
  builder.response :json
53
54
 
54
55
  if Restforce.log?
@@ -1,30 +1,155 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ #
4
+ # Taken from `lib/faraday_middleware/response/caching.rb` in the `faraday_middleware`
5
+ # gem (<https://github.com/lostisland/faraday_middleware/blob/784b4f8/lib/faraday_middleware/response/caching.rb>).
6
+ #
7
+ # Includes some small modifications to allow the cache to be cleared in
8
+ # `#without_caching` mode, replicating traditional Restforce behaviour.
9
+ #
10
+ # Copyright (c) 2011 Erik Michaels-Ober, Wynn Netherland, et al.
11
+ # Licensed under the MIT License.
12
+ #
13
+ require 'faraday'
14
+ require 'forwardable'
15
+ require 'digest/sha1'
16
+
3
17
  module Restforce
4
- class Middleware::Caching < FaradayMiddleware::Caching
5
- def call(env)
6
- expire(cache_key(env)) unless use_cache?
7
- super
18
+ # Public: Caches GET responses and pulls subsequent ones from the cache.
19
+ class Middleware::Caching < Faraday::Middleware
20
+ attr_reader :cache
21
+
22
+ # Internal: List of status codes that can be cached:
23
+ # * 200 - 'OK'
24
+ # * 203 - 'Non-Authoritative Information'
25
+ # * 300 - 'Multiple Choices'
26
+ # * 301 - 'Moved Permanently'
27
+ # * 302 - 'Found'
28
+ # * 404 - 'Not Found'
29
+ # * 410 - 'Gone'
30
+ CACHEABLE_STATUS_CODES = [200, 203, 300, 301, 302, 404, 410].freeze
31
+
32
+ extend Forwardable
33
+ def_delegators :'Faraday::Utils', :parse_query, :build_query
34
+
35
+ # Public: initialize the middleware.
36
+ #
37
+ # cache - An object that responds to read and write (default: nil).
38
+ # options - An options Hash (default: {}):
39
+ # :ignore_params - String name or Array names of query
40
+ # params that should be ignored when forming
41
+ # the cache key (default: []).
42
+ # :write_options - Hash of settings that should be passed as the
43
+ # third options parameter to the cache's #write
44
+ # method. If not specified, no options parameter
45
+ # will be passed.
46
+ # :full_key - Boolean - use full URL as cache key:
47
+ # (url.host + url.request_uri)
48
+ # :status_codes - Array of http status code to be cache
49
+ # (default: CACHEABLE_STATUS_CODE)
50
+ #
51
+ # Yields if no cache is given. The block should return a cache object.
52
+ def initialize(app, cache = nil, options = {})
53
+ super(app)
54
+ if cache.is_a?(Hash) && block_given?
55
+ options = cache
56
+ cache = nil
57
+ end
58
+ @cache = cache || yield
59
+ @options = options
8
60
  end
9
61
 
10
- def expire(key)
11
- cache&.delete(key)
62
+ def call(env)
63
+ # Taken from `Restforce::Middleware::Caching` implementation
64
+ # before we switched away from the `faraday_middleware` gem.
65
+ # See https://github.com/restforce/restforce/blob/a08b9d6c5e277bd7111ffa7ed50465dd49c05fab/lib/restforce/middleware/caching.rb.
66
+ cache&.delete(cache_key(env)) unless use_cache?
67
+
68
+ if env[:method] == :get
69
+ if env[:parallel_manager]
70
+ # callback mode
71
+ cache_on_complete(env)
72
+ else
73
+ # synchronous mode
74
+ key = cache_key(env)
75
+ unless (response = cache.read(key)) && response
76
+ response = @app.call(env)
77
+ store_response_in_cache(key, response)
78
+ end
79
+ finalize_response(response, env)
80
+ end
81
+ else
82
+ @app.call(env)
83
+ end
12
84
  end
13
85
 
14
- # We don't want to cache requests for different clients, so append the
15
- # oauth token to the cache key.
16
86
  def cache_key(env)
17
- super(env) + hashed_auth_header(env)
87
+ url = env[:url].dup
88
+ if url.query && params_to_ignore.any?
89
+ params = parse_query url.query
90
+ params.reject! { |k,| params_to_ignore.include? k }
91
+ url.query = params.any? ? build_query(params) : nil
92
+ end
93
+ url.normalize!
94
+ digest = full_key? ? url.host + url.request_uri : url.request_uri
95
+ Digest::SHA1.hexdigest(digest)
18
96
  end
19
97
 
20
- def use_cache?
21
- @options.fetch(:use_cache, true)
98
+ def params_to_ignore
99
+ @params_to_ignore ||= Array(@options[:ignore_params]).map(&:to_s)
100
+ end
101
+
102
+ def full_key?
103
+ @full_key ||= @options[:full_key]
22
104
  end
23
105
 
24
- def hashed_auth_header(env)
25
- Digest::SHA1.hexdigest(
26
- env[:request_headers][Restforce::Middleware::Authorization::AUTH_HEADER]
27
- )
106
+ def custom_status_codes
107
+ @custom_status_codes ||= begin
108
+ codes = CACHEABLE_STATUS_CODES & Array(@options[:status_codes]).map(&:to_i)
109
+ codes.any? ? codes : CACHEABLE_STATUS_CODES
110
+ end
111
+ end
112
+
113
+ def cache_on_complete(env)
114
+ key = cache_key(env)
115
+ if (cached_response = cache.read(key))
116
+ finalize_response(cached_response, env)
117
+ else
118
+ # response.status is nil at this point
119
+ # any checks need to be done inside on_complete block
120
+ @app.call(env).on_complete do |response_env|
121
+ store_response_in_cache(key, response_env.response)
122
+ response_env
123
+ end
124
+ end
125
+ end
126
+
127
+ def store_response_in_cache(key, response)
128
+ return unless custom_status_codes.include?(response.status)
129
+
130
+ if @options[:write_options]
131
+ cache.write(key, response, @options[:write_options])
132
+ else
133
+ cache.write(key, response)
134
+ end
135
+ end
136
+
137
+ def finalize_response(response, env)
138
+ response = response.dup if response.frozen?
139
+ env[:response] = response
140
+ unless env[:response_headers]
141
+ env.update response.env
142
+ # FIXME: omg hax
143
+ response.instance_variable_set('@env', env)
144
+ end
145
+ response
146
+ end
147
+
148
+ # Taken from `Restforce::Middleware::Caching` implementation
149
+ # before we switched away from the `faraday_middleware` gem.
150
+ # See https://github.com/restforce/restforce/blob/a08b9d6c5e277bd7111ffa7ed50465dd49c05fab/lib/restforce/middleware/caching.rb.
151
+ def use_cache?
152
+ @options[:use_cache]
28
153
  end
29
154
  end
30
155
  end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Adapted from `lib/faraday/request/json.rb` in the `faraday`
5
+ # gem (<https://github.com/lostisland/faraday/blob/5366029282968d59980a182258f8c2b0212721c8/lib/faraday/request/json.rb>).
6
+ #
7
+ # We use this because we want to support Faraday 1.x and Faraday 2.x.
8
+ # Faraday 2.x has the JSON middlewares included, but Faraday 1.x doesn't,
9
+ # forcing you to use the `faraday_middleware` gem. This approach allows us
10
+ # to support both.
11
+ #
12
+ # Copyright (c) 2009-2022 Rick Olson, Zack Hobson
13
+ # Licensed under the MIT License.
14
+ #
15
+ require 'json'
16
+
17
+ module Restforce
18
+ # Request middleware that encodes the body as JSON.
19
+ #
20
+ # Processes only requests with matching Content-type or those without a type.
21
+ # If a request doesn't have a type but has a body, it sets the Content-type
22
+ # to JSON MIME-type.
23
+ #
24
+ # Doesn't try to encode bodies that already are in string form.
25
+ # rubocop:disable Style/ClassAndModuleChildren
26
+ class Middleware::JsonRequest < Faraday::Middleware
27
+ # rubocop:enable Style/ClassAndModuleChildren
28
+
29
+ # This is the only line that differs substantively from the version in
30
+ # Faraday. In Faraday, this refers to a Faraday constant.
31
+ CONTENT_TYPE = 'Content-Type'
32
+
33
+ MIME_TYPE = 'application/json'
34
+ MIME_TYPE_REGEX = %r{^application/(vnd\..+\+)?json$}.freeze
35
+
36
+ #
37
+ # Taken from `lib/faraday/middleware.rb` in the `faraday`
38
+ # gem (<https://github.com/lostisland/faraday/blob/08b7d4d/lib/faraday/middleware.rb>),
39
+ # with a tiny adaptation to refer to the `@app` instance
40
+ # variable rather than expecting an `attr_reader` to exist.
41
+ #
42
+ # In Faraday versions before v1.2.0, `#call` is missing.
43
+ #
44
+ # Copyright (c) 2009-2022 Rick Olson, Zack Hobson
45
+ # Licensed under the MIT License.
46
+ #
47
+ def call(env)
48
+ on_request(env) if respond_to?(:on_request)
49
+ @app.call(env).on_complete do |environment|
50
+ on_complete(environment) if respond_to?(:on_complete)
51
+ end
52
+ end
53
+
54
+ def on_request(env)
55
+ match_content_type(env) do |data|
56
+ env[:body] = encode(data)
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def encode(data)
63
+ ::JSON.generate(data)
64
+ end
65
+
66
+ def match_content_type(env)
67
+ return unless process_request?(env)
68
+
69
+ env[:request_headers][CONTENT_TYPE] ||= MIME_TYPE
70
+ yield env[:body] unless env[:body].respond_to?(:to_str)
71
+ end
72
+
73
+ def process_request?(env)
74
+ type = request_type(env)
75
+ body?(env) && (type.empty? || type.match?(MIME_TYPE_REGEX))
76
+ end
77
+
78
+ def body?(env)
79
+ (body = env[:body]) && !(body.respond_to?(:to_str) && body.empty?)
80
+ end
81
+
82
+ def request_type(env)
83
+ type = env[:request_headers][CONTENT_TYPE].to_s
84
+ type = type.split(';', 2).first if type.index(';')
85
+ type
86
+ end
87
+ end
88
+ end
89
+
90
+ Faraday::Request.register_middleware(json: Restforce::Middleware::JsonRequest)
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Adapted from `lib/faraday/response/json.rb` in the `faraday`
5
+ # gem (<https://github.com/lostisland/faraday/blob/5366029/lib/faraday/response/json.rb>).
6
+ #
7
+ # Copyright (c) 2009-2022 Rick Olson, Zack Hobson
8
+ # Licensed under the MIT License.
9
+ #
10
+
11
+ require 'json'
12
+
13
+ module Restforce
14
+ # rubocop:disable Style/ClassAndModuleChildren
15
+ class Middleware::JsonResponse < Faraday::Middleware
16
+ # rubocop:enable Style/ClassAndModuleChildren
17
+
18
+ # This is the only line that differs substantively from the version in
19
+ # Faraday. In Faraday, this refers to a Faraday constant.
20
+ CONTENT_TYPE = 'Content-Type'
21
+
22
+ def initialize(app = nil, parser_options: nil, content_type: /\bjson$/,
23
+ preserve_raw: false)
24
+ super(app)
25
+ @parser_options = parser_options
26
+ @content_types = Array(content_type)
27
+ @preserve_raw = preserve_raw
28
+ end
29
+
30
+ #
31
+ # Taken from `lib/faraday/middleware.rb` in the `faraday`
32
+ # gem (<https://github.com/lostisland/faraday/blob/08b7d4d/lib/faraday/middleware.rb>),
33
+ # with a tiny adaptation to refer to the `@app` instance
34
+ # variable rather than expecting an `attr_reader` to exist.
35
+ #
36
+ # In Faraday versions before v1.2.0, `#call` is missing.
37
+ #
38
+ # Copyright (c) 2009-2022 Rick Olson, Zack Hobson
39
+ # Licensed under the MIT License.
40
+ #
41
+ def call(env)
42
+ on_request(env) if respond_to?(:on_request)
43
+ @app.call(env).on_complete do |environment|
44
+ on_complete(environment) if respond_to?(:on_complete)
45
+ end
46
+ end
47
+
48
+ def on_complete(env)
49
+ process_response(env) if parse_response?(env)
50
+ end
51
+
52
+ private
53
+
54
+ def process_response(env)
55
+ env[:raw_body] = env[:body] if @preserve_raw
56
+ env[:body] = parse(env[:body])
57
+ rescue StandardError, SyntaxError => e
58
+ raise Faraday::ParsingError.new(e, env[:response])
59
+ end
60
+
61
+ def parse(body)
62
+ ::JSON.parse(body, @parser_options || {}) unless body.strip.empty?
63
+ end
64
+
65
+ def parse_response?(env)
66
+ process_response_type?(env) &&
67
+ env[:body].respond_to?(:to_str)
68
+ end
69
+
70
+ def process_response_type?(env)
71
+ type = response_type(env)
72
+ @content_types.empty? || @content_types.any? do |pattern|
73
+ pattern.is_a?(Regexp) ? type.match?(pattern) : type == pattern
74
+ end
75
+ end
76
+
77
+ def response_type(env)
78
+ type = env[:response_headers][CONTENT_TYPE].to_s
79
+ type = type.split(';', 2).first if type.index(';')
80
+ type
81
+ end
82
+ end
83
+ end
84
+
85
+ Faraday::Response.register_middleware(json: Restforce::Middleware::JsonResponse)
@@ -3,7 +3,7 @@
3
3
  require 'forwardable'
4
4
 
5
5
  module Restforce
6
- class Middleware::Logger < Faraday::Response::Middleware
6
+ class Middleware::Logger < Faraday::Middleware
7
7
  extend Forwardable
8
8
 
9
9
  def initialize(app, logger, options)
@@ -11,7 +11,7 @@ module Restforce
11
11
  @options = options
12
12
  @logger = logger || begin
13
13
  require 'logger'
14
- ::Logger.new(STDOUT)
14
+ ::Logger.new($stdout)
15
15
  end
16
16
  end
17
17
 
@@ -20,23 +20,28 @@ module Restforce
20
20
  def call(env)
21
21
  debug('request') do
22
22
  dump url: env[:url].to_s,
23
- method: env[:method],
24
- headers: env[:request_headers],
25
- body: env[:body]
23
+ method: env[:method],
24
+ headers: env[:request_headers],
25
+ body: env[:body]
26
+ end
27
+
28
+ on_request(env) if respond_to?(:on_request)
29
+ @app.call(env).on_complete do |environment|
30
+ on_complete(environment) if respond_to?(:on_complete)
26
31
  end
27
- super
28
32
  end
29
33
 
30
34
  def on_complete(env)
31
35
  debug('response') do
32
36
  dump status: env[:status].to_s,
33
- headers: env[:response_headers],
34
- body: env[:body]
37
+ headers: env[:response_headers],
38
+ body: env[:body]
35
39
  end
36
40
  end
37
41
 
38
42
  def dump(hash)
39
- "\n" + hash.map { |k, v| " #{k}: #{v.inspect}" }.join("\n")
43
+ dumped_pairs = hash.map { |k, v| " #{k}: #{v.inspect}" }.join("\n")
44
+ "\n#{dumped_pairs}"
40
45
  end
41
46
  end
42
47
  end
@@ -1,7 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Restforce
4
- class Middleware::RaiseError < Faraday::Response::Middleware
4
+ class Middleware::RaiseError < Faraday::Middleware
5
+ # Required for Faraday versions pre-v1.2.0 which do not include
6
+ # an implementation of `#call` by default
7
+ def call(env)
8
+ on_request(env) if respond_to?(:on_request)
9
+ @app.call(env).on_complete do |environment|
10
+ on_complete(environment) if respond_to?(:on_complete)
11
+ end
12
+ end
13
+
5
14
  def on_complete(env)
6
15
  @env = env
7
16
  case env[:status]
@@ -11,9 +20,9 @@ module Restforce
11
20
  response_values
12
21
  )
13
22
  when 401
14
- raise Restforce::UnauthorizedError, message
23
+ raise Restforce::UnauthorizedError.new(message, response_values)
15
24
  when 404
16
- raise Restforce::NotFoundError, message
25
+ raise Restforce::NotFoundError.new(message, response_values)
17
26
  when 413
18
27
  raise Restforce::EntityTooLargeError.new(
19
28
  "413: Request Entity Too Large",
@@ -56,8 +65,7 @@ module Restforce
56
65
  def exception_class_for_error_code(error_code)
57
66
  return Restforce::ResponseError unless ERROR_CODE_MATCHER.match?(error_code)
58
67
 
59
- constant_name = error_code.split('_').map(&:capitalize).join.to_sym
60
- Restforce::ErrorCode.const_get(constant_name)
68
+ Restforce::ErrorCode.get_exception_class(error_code)
61
69
  end
62
70
  end
63
71
  end
@@ -16,6 +16,8 @@ module Restforce
16
16
  autoload :CustomHeaders, 'restforce/middleware/custom_headers'
17
17
 
18
18
  def initialize(app, client, options)
19
+ super(app)
20
+
19
21
  @app = app
20
22
  @client = client
21
23
  @options = options
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Restforce
4
- VERSION = '4.2.1'
4
+ VERSION = '6.0.0'
5
5
  end
data/lib/restforce.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'faraday'
4
- require 'faraday_middleware'
4
+ require 'faraday/follow_redirects'
5
5
  require 'json'
6
6
  require 'jwt'
7
7
 
@@ -15,7 +15,8 @@ module Restforce
15
15
  autoload :Middleware, 'restforce/middleware'
16
16
  autoload :Attachment, 'restforce/attachment'
17
17
  autoload :Document, 'restforce/document'
18
- autoload :UploadIO, 'restforce/upload_io'
18
+ autoload :FilePart, 'restforce/file_part'
19
+ autoload :UploadIO, 'restforce/file_part' # Deprecated
19
20
  autoload :SObject, 'restforce/sobject'
20
21
  autoload :Client, 'restforce/client'
21
22
  autoload :Mash, 'restforce/mash'
@@ -31,6 +32,7 @@ module Restforce
31
32
  autoload :Base, 'restforce/concerns/base'
32
33
  autoload :API, 'restforce/concerns/api'
33
34
  autoload :BatchAPI, 'restforce/concerns/batch_api'
35
+ autoload :CompositeAPI, 'restforce/concerns/composite_api'
34
36
  end
35
37
 
36
38
  module Data
@@ -44,9 +46,10 @@ module Restforce
44
46
  Error = Class.new(StandardError)
45
47
  ServerError = Class.new(Error)
46
48
  AuthenticationError = Class.new(Error)
47
- UnauthorizedError = Class.new(Error)
49
+ UnauthorizedError = Class.new(Faraday::ClientError)
48
50
  APIVersionError = Class.new(Error)
49
51
  BatchAPIError = Class.new(Error)
52
+ CompositeAPIError = Class.new(Error)
50
53
 
51
54
  # Inherit from Faraday::ResourceNotFound for backwards-compatibility
52
55
  # Consumers of this library that rescue and handle Faraday::ResourceNotFound
@@ -60,26 +63,24 @@ module Restforce
60
63
  MatchesMultipleError= Class.new(ResponseError)
61
64
  EntityTooLargeError = Class.new(ResponseError)
62
65
 
63
- module ErrorCode
64
- def self.const_missing(constant_name)
65
- const_set constant_name, Class.new(ResponseError)
66
- end
67
- end
66
+ require 'restforce/error_code'
67
+ require 'restforce/middleware/json_request'
68
+ require 'restforce/middleware/json_response'
68
69
 
69
70
  class << self
70
71
  # Alias for Restforce::Data::Client.new
71
72
  #
72
73
  # Shamelessly pulled from https://github.com/pengwynn/octokit/blob/master/lib/octokit.rb
73
- def new(*args, &block)
74
- data(*args, &block)
74
+ def new(...)
75
+ data(...)
75
76
  end
76
77
 
77
- def data(*args, &block)
78
- Restforce::Data::Client.new(*args, &block)
78
+ def data(...)
79
+ Restforce::Data::Client.new(...)
79
80
  end
80
81
 
81
- def tooling(*args, &block)
82
- Restforce::Tooling::Client.new(*args, &block)
82
+ def tooling(...)
83
+ Restforce::Tooling::Client.new(...)
83
84
  end
84
85
 
85
86
  # Helper for decoding signed requests.
data/restforce.gemspec CHANGED
@@ -3,39 +3,31 @@
3
3
  require File.expand_path('lib/restforce/version', __dir__)
4
4
 
5
5
  Gem::Specification.new do |gem|
6
- gem.authors = ["Eric J. Holmes", "Tim Rogers"]
7
- gem.email = ["eric@ejholmes.net", "tim@gocardless.com"]
8
- gem.description = 'A lightweight ruby client for the Salesforce REST API.'
9
- gem.summary = 'A lightweight ruby client for the Salesforce REST API.'
10
- gem.homepage = "http://restforce.org/"
6
+ gem.authors = ["Tim Rogers", "Eric J. Holmes"]
7
+ gem.email = ["me@timrogers.co.uk", "eric@ejholmes.net"]
8
+ gem.description = 'A lightweight Ruby client for the Salesforce REST API'
9
+ gem.summary = 'A lightweight Ruby client for the Salesforce REST API'
10
+ gem.homepage = "https://restforce.github.io/"
11
11
  gem.license = "MIT"
12
12
 
13
13
  gem.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
14
14
  gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
15
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
16
15
  gem.name = "restforce"
17
16
  gem.require_paths = ["lib"]
18
17
  gem.version = Restforce::VERSION
19
18
 
20
19
  gem.metadata = {
21
20
  'source_code_uri' => 'https://github.com/restforce/restforce',
22
- 'changelog_uri' => 'https://github.com/restforce/restforce/blob/master/CHANGELOG.md'
21
+ 'changelog_uri' => 'https://github.com/restforce/restforce/blob/master/CHANGELOG.md',
22
+ 'rubygems_mfa_required' => 'true'
23
23
  }
24
24
 
25
- gem.required_ruby_version = '>= 2.4'
25
+ gem.required_ruby_version = '>= 2.7'
26
26
 
27
- gem.add_dependency 'faraday', '<= 1.0', '>= 0.9.0'
28
- gem.add_dependency 'faraday_middleware', ['>= 0.8.8', '<= 1.0']
29
-
30
- gem.add_dependency 'json', '>= 1.7.5'
27
+ gem.add_dependency 'faraday', '< 2.5.0', '>= 1.1.0'
28
+ gem.add_dependency 'faraday-follow_redirects', '<= 0.3.0', '< 1.0.0'
29
+ gem.add_dependency 'faraday-multipart', '>= 1.0.0', '< 2.0.0'
30
+ gem.add_dependency 'faraday-net_http', '< 3.0.0'
31
+ gem.add_dependency 'hashie', '>= 1.2.0', '< 6.0'
31
32
  gem.add_dependency 'jwt', ['>= 1.5.6']
32
-
33
- gem.add_dependency 'hashie', '>= 1.2.0', '< 5.0'
34
-
35
- gem.add_development_dependency 'faye' unless RUBY_PLATFORM == 'java'
36
- gem.add_development_dependency 'rspec', '~> 2.14.0'
37
- gem.add_development_dependency 'rspec_junit_formatter', '~> 0.4.1'
38
- gem.add_development_dependency 'rubocop', '~> 0.77.0'
39
- gem.add_development_dependency 'simplecov', '~> 0.17.1'
40
- gem.add_development_dependency 'webmock', '~> 3.7.6'
41
33
  end