peddler 4.3.1 → 4.5.0

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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +459 -109
  3. data/lib/peddler/api.rb +13 -11
  4. data/lib/peddler/apis/amazon_warehousing_and_distribution_2024_05_09.rb +7 -7
  5. data/lib/peddler/apis/aplus_content_2020_11_01.rb +10 -10
  6. data/lib/peddler/apis/application_integrations_2024_04_01.rb +1 -1
  7. data/lib/peddler/apis/catalog_items_2020_12_01.rb +8 -8
  8. data/lib/peddler/apis/catalog_items_2022_04_01.rb +9 -9
  9. data/lib/peddler/apis/customer_feedback_2024_06_01.rb +143 -0
  10. data/lib/peddler/apis/data_kiosk_2023_11_15.rb +4 -4
  11. data/lib/peddler/apis/fba_inbound_eligibility_v1.rb +1 -1
  12. data/lib/peddler/apis/fba_inventory_v1.rb +3 -3
  13. data/lib/peddler/apis/feeds_2021_06_30.rb +6 -6
  14. data/lib/peddler/apis/finances_2024_06_01.rb +1 -1
  15. data/lib/peddler/apis/finances_2024_06_19.rb +14 -6
  16. data/lib/peddler/apis/finances_v0.rb +2 -2
  17. data/lib/peddler/apis/fulfillment_inbound_2024_03_20.rb +40 -40
  18. data/lib/peddler/apis/fulfillment_inbound_v0.rb +8 -8
  19. data/lib/peddler/apis/fulfillment_outbound_2020_07_01.rb +7 -7
  20. data/lib/peddler/apis/invoices_2024_06_19.rb +4 -4
  21. data/lib/peddler/apis/listings_items_2020_09_01.rb +6 -6
  22. data/lib/peddler/apis/listings_items_2021_08_01.rb +20 -26
  23. data/lib/peddler/apis/listings_restrictions_2021_08_01.rb +1 -1
  24. data/lib/peddler/apis/merchant_fulfillment_v0.rb +2 -2
  25. data/lib/peddler/apis/messaging_v1.rb +26 -26
  26. data/lib/peddler/apis/notifications_v1.rb +6 -6
  27. data/lib/peddler/apis/orders_v0.rb +20 -20
  28. data/lib/peddler/apis/product_fees_v0.rb +2 -2
  29. data/lib/peddler/apis/product_pricing_v0.rb +6 -6
  30. data/lib/peddler/apis/product_type_definitions_2020_09_01.rb +4 -4
  31. data/lib/peddler/apis/reports_2021_06_30.rb +12 -9
  32. data/lib/peddler/apis/sales_v1.rb +7 -2
  33. data/lib/peddler/apis/seller_wallet_2024_03_01.rb +5 -5
  34. data/lib/peddler/apis/services_v1.rb +27 -27
  35. data/lib/peddler/apis/shipment_invoicing_v0.rb +3 -3
  36. data/lib/peddler/apis/shipping_v1.rb +5 -5
  37. data/lib/peddler/apis/shipping_v2.rb +6 -6
  38. data/lib/peddler/apis/solicitations_v1.rb +4 -4
  39. data/lib/peddler/apis/supply_sources_2020_07_01.rb +4 -4
  40. data/lib/peddler/apis/uploads_2020_11_01.rb +2 -2
  41. data/lib/peddler/apis/vendor_direct_fulfillment_inventory_v1.rb +1 -1
  42. data/lib/peddler/apis/vendor_direct_fulfillment_orders_2021_12_28.rb +1 -1
  43. data/lib/peddler/apis/vendor_direct_fulfillment_orders_v1.rb +1 -1
  44. data/lib/peddler/apis/vendor_direct_fulfillment_sandbox_test_data_2021_10_28.rb +1 -1
  45. data/lib/peddler/apis/vendor_direct_fulfillment_shipping_2021_12_28.rb +4 -4
  46. data/lib/peddler/apis/vendor_direct_fulfillment_shipping_v1.rb +3 -3
  47. data/lib/peddler/apis/vendor_direct_fulfillment_transactions_2021_12_28.rb +1 -1
  48. data/lib/peddler/apis/vendor_direct_fulfillment_transactions_v1.rb +1 -1
  49. data/lib/peddler/apis/vendor_orders_v1.rb +1 -1
  50. data/lib/peddler/apis/vendor_shipments_v1.rb +1 -1
  51. data/lib/peddler/apis/vendor_transaction_status_v1.rb +1 -1
  52. data/lib/peddler/config.rb +17 -0
  53. data/lib/peddler/error.rb +35 -8
  54. data/lib/peddler/helpers/feeds_2021_06_30.rb +22 -8
  55. data/lib/peddler/helpers/reports_2021_06_30.rb +38 -0
  56. data/lib/peddler/marketplace.rb +14 -0
  57. data/lib/peddler/response.rb +52 -5
  58. data/lib/peddler/token.rb +4 -15
  59. data/lib/peddler/version.rb +1 -1
  60. data/lib/peddler.rb +54 -0
  61. metadata +8 -13
  62. data/lib/peddler/parsers/openapi_parser_generator.rb +0 -550
  63. data/lib/peddler/parsers/smart_parser.rb +0 -199
data/lib/peddler/error.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "json"
4
+
3
5
  module Peddler
4
6
  class Error < StandardError
5
7
  attr_reader :response
@@ -7,16 +9,29 @@ module Peddler
7
9
  # @!visibility private
8
10
  class << self
9
11
  def build(response)
10
- error = JSON.parse(response).dig("errors").first
11
- class_name = normalize_class_name(error.dig("code"))
12
- message = error.dig("message")
12
+ payload = begin
13
+ JSON.parse(response)
14
+ rescue JSON::ParserError
15
+ parse_xml_error(response)
16
+ end
17
+
18
+ if payload.key?("error")
19
+ class_name = normalize_class_name(payload["error"])
20
+ message = payload["error_description"]
21
+ elsif payload.key?("errors")
22
+ class_name = normalize_class_name(payload.dig("errors", 0, "code"))
23
+ message = payload.dig("errors", 0, "message")
24
+ elsif payload.key?("Code")
25
+ class_name = payload["Code"]
26
+ message = payload["Message"]
27
+ else
28
+ return
29
+ end
30
+
13
31
  klass = if Errors.const_defined?(class_name)
14
32
  Errors.const_get(class_name)
15
33
  else
16
- Errors.const_set(
17
- class_name,
18
- Class.new(Error),
19
- )
34
+ Errors.const_set(class_name, Class.new(Error))
20
35
  end
21
36
 
22
37
  klass.new(message, response)
@@ -26,8 +41,16 @@ module Peddler
26
41
 
27
42
  private
28
43
 
44
+ def parse_xml_error(response)
45
+ require "nokogiri"
46
+ doc = Nokogiri::XML(response)
47
+ Hash[doc.root.elements.collect { |e| [e.name, e.text] }]
48
+ rescue LoadError, NoMethodError
49
+ {}
50
+ end
51
+
29
52
  def normalize_class_name(code)
30
- if code.match?(/\A[A-Z_]+\z/)
53
+ if code.match?(/\A([a-z_]+|[A-Z_]+)\z/)
31
54
  code.split("_").map(&:capitalize).join
32
55
  else
33
56
  code
@@ -42,9 +65,13 @@ module Peddler
42
65
  end
43
66
 
44
67
  module Errors
68
+ class AccessDenied < Error; end
69
+ class InvalidGrant < Error; end
45
70
  class InvalidInput < Error; end
71
+ class InvalidRequest < Error; end
46
72
  class NotFound < Error; end
47
73
  class QuotaExceeded < Error; end
48
74
  class Unauthorized < Error; end
75
+ class UnsupportedGrantType < Error; end
49
76
  end
50
77
  end
@@ -1,11 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "http"
4
+
5
+ require "peddler/response"
6
+
3
7
  module Peddler
4
8
  module Helpers
5
9
  module Feeds20210630
6
- # Uploads feed_content to a signed upload_url previously provided by
7
- # create_feed_document. The upload_url is signed, the Host and content-type
8
- # headers must match the signing.
10
+ # Convenience method to upload feed content to a signed upload_url previously
11
+ # provided by create_feed_document. This is step 2 of the 6-step Feeds API workflow.
12
+ # See README.md for the complete workflow documentation.
13
+ #
14
+ # The upload_url is signed, the Host and content-type headers must match the signing.
9
15
  # @param upload_url [String] The signed url from the `create_feed_document` response.
10
16
  # @param feed_content [String] The body of the content to upload.
11
17
  # @param content_type [String] The content type of the upload,
@@ -14,12 +20,20 @@ module Peddler
14
20
  def upload_feed_document(upload_url, feed_content, content_type)
15
21
  response = HTTP.headers("content-type" => content_type).put(upload_url, body: feed_content)
16
22
 
17
- if response.status.client_error?
18
- error = Error.build(response)
19
- raise error if error
20
- end
23
+ Response.wrap(response, parser:)
24
+ end
25
+
26
+ # Convenience method to download result feed content from a signed download_url
27
+ # provided by get_feed_document. This is step 6 of the 6-step Feeds API workflow.
28
+ # See README.md for the complete workflow documentation.
29
+ #
30
+ # The download_url is signed and provides access to the processed feed results.
31
+ # @param download_url [String] The signed url from the `get_feed_document` response.
32
+ # @return [HTTP::Response] The API response containing the feed result document
33
+ def download_result_feed_document(download_url)
34
+ response = HTTP.get(download_url)
21
35
 
22
- response
36
+ Response.wrap(response, parser:)
23
37
  end
24
38
  end
25
39
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "http"
4
+
5
+ require "peddler/response"
6
+ require "peddler/error"
7
+
8
+ module Peddler
9
+ module Helpers
10
+ module Reports20210630
11
+ # Convenience method to download a report by its document ID or URL.
12
+ # This method can handle both document IDs and direct download URLs.
13
+ #
14
+ # @param report_document_id_or_url [String] The report document identifier or download URL
15
+ # @return [HTTP::Response] The API response containing the report content
16
+ def download_report_document(report_document_id_or_url)
17
+ # If it looks like a URL, use direct download
18
+ if report_document_id_or_url.start_with?("http")
19
+ return download_report_document_from_url(report_document_id_or_url)
20
+ end
21
+
22
+ # Otherwise, treat it as a document ID and get the download URL first
23
+ document_info = get_report_document(report_document_id_or_url)
24
+ download_url = document_info.dig("url")
25
+
26
+ download_report_document_from_url(download_url)
27
+ end
28
+
29
+ private
30
+
31
+ def download_report_document_from_url(download_url)
32
+ response = HTTP.get(download_url)
33
+
34
+ Response.wrap(response, parser:)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -77,6 +77,20 @@ module Peddler
77
77
  new(**values, country_code: country_code)
78
78
  end
79
79
  end
80
+
81
+ # Dynamically generate shorthand methods for each country code
82
+ # e.g., Marketplace.us returns the US marketplace
83
+ MARKETPLACE_IDS.each_key do |country_code|
84
+ method_name = country_code.downcase
85
+ define_method(method_name) do
86
+ find(country_code)
87
+ end
88
+ end
89
+
90
+ # Special alias for GB (Great Britain) -> UK
91
+ define_method(:gb) do
92
+ find("GB")
93
+ end
80
94
  end
81
95
 
82
96
  # @return [Peddler::Endpoint]
@@ -3,6 +3,9 @@
3
3
  require "delegate"
4
4
  require "forwardable"
5
5
 
6
+ require "peddler/config"
7
+ require "peddler/error"
8
+
6
9
  module Peddler
7
10
  # Wraps HTTP::Response to allow custom parsing
8
11
  class Response < SimpleDelegator
@@ -17,16 +20,60 @@ module Peddler
17
20
  def_delegator :to_h, :dig
18
21
 
19
22
  class << self
20
- # Decorates an HTTP::Response
23
+ # Wraps an HTTP::Response with parsing capabilities
21
24
  #
22
25
  # @param [HTTP::Response] response
23
26
  # @param [nil, #call] parser (if any)
24
- # @return [ResponseDecorator]
25
- def decorate(response, parser: nil)
26
- new(response).tap do |decorator|
27
- decorator.parser = parser
27
+ # @return [Response]
28
+ # @raise [Error] if response status indicates an error (>= 400)
29
+ def wrap(response, parser: nil)
30
+ # Check for HTTP errors and raise custom Peddler errors
31
+ if response.status >= 400
32
+ # Client errors (4xx) always raise
33
+ if response.status < 500
34
+ error = Error.build(response)
35
+ raise error || Error.new(response.status, response)
36
+ # Server errors (5xx) - check configuration
37
+ elsif Peddler.raise_on_server_errors
38
+ error = Error.build(response)
39
+ raise error || Error.new(response.status, response)
40
+ else
41
+ # Emit deprecation warning for v4 behavior
42
+ warn_about_server_error_handling
43
+ end
44
+ end
45
+
46
+ new(response).tap do |wrapper|
47
+ wrapper.parser = parser
28
48
  end
29
49
  end
50
+
51
+ # @deprecated Use {.wrap} instead
52
+ def decorate(...)
53
+ warn("Response.decorate is deprecated and will be removed in v5.0. Use Response.wrap instead.", uplevel: 1)
54
+ wrap(...)
55
+ end
56
+
57
+ private
58
+
59
+ def warn_about_server_error_handling
60
+ return if @deprecation_warned
61
+
62
+ @deprecation_warned = true
63
+
64
+ warn(<<~MSG)
65
+ [DEPRECATION] Peddler v4 behavior: Server errors (5xx) are returning response objects instead of raising exceptions.
66
+ This behavior is deprecated and will change in Peddler v5.0.
67
+
68
+ To adopt the new behavior now and silence this warning:
69
+
70
+ Peddler.configure do |config|
71
+ config.raise_on_server_errors = true
72
+ end
73
+
74
+ For more information, see: https://github.com/hakanensari/peddler/blob/main/CHANGELOG.md
75
+ MSG
76
+ end
30
77
  end
31
78
 
32
79
  # @return [#call]
data/lib/peddler/token.rb CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  require "http"
4
4
 
5
+ require "peddler/response"
6
+
5
7
  module Peddler
6
8
  # Requests refresh and access tokens that authorize your application to take actions on behalf of a selling partner.
7
9
  #
@@ -9,14 +11,7 @@ module Peddler
9
11
  #
10
12
  # @see https://developer-docs.amazon.com/sp-api/docs/connecting-to-the-selling-partner-api
11
13
  class Token
12
- class Error < StandardError
13
- attr_reader :response
14
-
15
- def initialize(msg = nil, response = nil)
16
- @response = response
17
- super(msg)
18
- end
19
- end
14
+ Error = Class.new(Peddler::Error)
20
15
 
21
16
  URL = "https://api.amazon.com/auth/o2/token"
22
17
 
@@ -36,13 +31,7 @@ module Peddler
36
31
 
37
32
  def request
38
33
  response = HTTP.post(URL, form: params)
39
-
40
- unless response.status.success?
41
- message = response.parse["error_description"] || "Unknown token error"
42
- raise Error.new(message, response)
43
- end
44
-
45
- response
34
+ Response.wrap(response)
46
35
  end
47
36
 
48
37
  def grant_type
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Peddler
4
- VERSION = "4.3.1"
4
+ VERSION = "4.5.0"
5
5
  end
data/lib/peddler.rb CHANGED
@@ -7,6 +7,7 @@ require "peddler/apis/application_management_2023_11_30"
7
7
  require "peddler/apis/catalog_items_2020_12_01"
8
8
  require "peddler/apis/catalog_items_2022_04_01"
9
9
  require "peddler/apis/catalog_items_v0"
10
+ require "peddler/apis/customer_feedback_2024_06_01"
10
11
  require "peddler/apis/data_kiosk_2023_11_15"
11
12
  require "peddler/apis/easy_ship_2022_03_23"
12
13
  require "peddler/apis/fba_inbound_eligibility_v1"
@@ -57,4 +58,57 @@ require "peddler/apis/vendor_invoices_v1"
57
58
  require "peddler/apis/vendor_orders_v1"
58
59
  require "peddler/apis/vendor_shipments_v1"
59
60
  require "peddler/apis/vendor_transaction_status_v1"
61
+ require "peddler/config"
60
62
  require "peddler/token"
63
+
64
+ module Peddler
65
+ class << self
66
+ alias_method :amazon_warehousing_and_distribution, :amazon_warehousing_and_distribution_2024_05_09
67
+ alias_method :aplus_content, :aplus_content_2020_11_01
68
+ alias_method :application_integrations, :application_integrations_2024_04_01
69
+ alias_method :application_management, :application_management_2023_11_30
70
+ alias_method :catalog_items, :catalog_items_2022_04_01
71
+ alias_method :customer_feedback, :customer_feedback_2024_06_01
72
+ alias_method :data_kiosk, :data_kiosk_2023_11_15
73
+ alias_method :easy_ship, :easy_ship_2022_03_23
74
+ alias_method :fba_inbound_eligibility, :fba_inbound_eligibility_v1
75
+ alias_method :fba_inventory, :fba_inventory_v1
76
+ alias_method :feeds, :feeds_2021_06_30
77
+ alias_method :finances, :finances_2024_06_19
78
+ alias_method :fulfillment_inbound, :fulfillment_inbound_2024_03_20
79
+ alias_method :fulfillment_outbound, :fulfillment_outbound_2020_07_01
80
+ alias_method :invoices, :invoices_2024_06_19
81
+ alias_method :listings_items, :listings_items_2021_08_01
82
+ alias_method :listings_restrictions, :listings_restrictions_2021_08_01
83
+ alias_method :merchant_fulfillment, :merchant_fulfillment_v0
84
+ alias_method :messaging, :messaging_v1
85
+ alias_method :notifications, :notifications_v1
86
+ alias_method :orders, :orders_v0
87
+ alias_method :product_fees, :product_fees_v0
88
+ alias_method :product_pricing, :product_pricing_2022_05_01
89
+ alias_method :product_type_definitions, :product_type_definitions_2020_09_01
90
+ alias_method :replenishment, :replenishment_2022_11_07
91
+ alias_method :reports, :reports_2021_06_30
92
+ alias_method :sales, :sales_v1
93
+ alias_method :seller_wallet, :seller_wallet_2024_03_01
94
+ alias_method :sellers, :sellers_v1
95
+ alias_method :services, :services_v1
96
+ alias_method :shipment_invoicing, :shipment_invoicing_v0
97
+ alias_method :shipping, :shipping_v2
98
+ alias_method :solicitations, :solicitations_v1
99
+ alias_method :supply_sources, :supply_sources_2020_07_01
100
+ alias_method :tokens, :tokens_2021_03_01
101
+ alias_method :uploads, :uploads_2020_11_01
102
+ alias_method :vehicles, :vehicles_2024_11_01
103
+ alias_method :vendor_direct_fulfillment_inventory, :vendor_direct_fulfillment_inventory_v1
104
+ alias_method :vendor_direct_fulfillment_orders, :vendor_direct_fulfillment_orders_2021_12_28
105
+ alias_method :vendor_direct_fulfillment_payments, :vendor_direct_fulfillment_payments_v1
106
+ alias_method :vendor_direct_fulfillment_sandbox_test_data, :vendor_direct_fulfillment_sandbox_test_data_2021_10_28
107
+ alias_method :vendor_direct_fulfillment_shipping, :vendor_direct_fulfillment_shipping_2021_12_28
108
+ alias_method :vendor_direct_fulfillment_transactions, :vendor_direct_fulfillment_transactions_2021_12_28
109
+ alias_method :vendor_invoices, :vendor_invoices_v1
110
+ alias_method :vendor_orders, :vendor_orders_v1
111
+ alias_method :vendor_shipments, :vendor_shipments_v1
112
+ alias_method :vendor_transaction_status, :vendor_transaction_status_v1
113
+ end
114
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: peddler
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.3.1
4
+ version: 4.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hakan Ensari
@@ -13,22 +13,16 @@ dependencies:
13
13
  name: http
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
- - - ">="
16
+ - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: '5.0'
19
- - - "<"
20
- - !ruby/object:Gem::Version
21
- version: '7.0'
18
+ version: '5.3'
22
19
  type: :runtime
23
20
  prerelease: false
24
21
  version_requirements: !ruby/object:Gem::Requirement
25
22
  requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- version: '5.0'
29
- - - "<"
23
+ - - "~>"
30
24
  - !ruby/object:Gem::Version
31
- version: '7.0'
25
+ version: '5.3'
32
26
  email:
33
27
  - hakanensari@gmail.com
34
28
  executables: []
@@ -46,6 +40,7 @@ files:
46
40
  - lib/peddler/apis/catalog_items_2020_12_01.rb
47
41
  - lib/peddler/apis/catalog_items_2022_04_01.rb
48
42
  - lib/peddler/apis/catalog_items_v0.rb
43
+ - lib/peddler/apis/customer_feedback_2024_06_01.rb
49
44
  - lib/peddler/apis/data_kiosk_2023_11_15.rb
50
45
  - lib/peddler/apis/easy_ship_2022_03_23.rb
51
46
  - lib/peddler/apis/fba_inbound_eligibility_v1.rb
@@ -96,12 +91,12 @@ files:
96
91
  - lib/peddler/apis/vendor_orders_v1.rb
97
92
  - lib/peddler/apis/vendor_shipments_v1.rb
98
93
  - lib/peddler/apis/vendor_transaction_status_v1.rb
94
+ - lib/peddler/config.rb
99
95
  - lib/peddler/endpoint.rb
100
96
  - lib/peddler/error.rb
101
97
  - lib/peddler/helpers/feeds_2021_06_30.rb
98
+ - lib/peddler/helpers/reports_2021_06_30.rb
102
99
  - lib/peddler/marketplace.rb
103
- - lib/peddler/parsers/openapi_parser_generator.rb
104
- - lib/peddler/parsers/smart_parser.rb
105
100
  - lib/peddler/response.rb
106
101
  - lib/peddler/token.rb
107
102
  - lib/peddler/version.rb