peddler 2.1.0 → 2.4.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of peddler might be problematic. Click here for more details.

Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +43 -41
  3. data/lib/mws.rb +2 -1
  4. data/lib/mws/easy_ship.rb +3 -0
  5. data/lib/mws/easy_ship/client.rb +93 -0
  6. data/lib/mws/fulfillment_inbound_shipment/client.rb +2 -2
  7. data/lib/mws/fulfillment_outbound_shipment/client.rb +1 -1
  8. data/lib/mws/orders/client.rb +7 -9
  9. data/lib/mws/reports/client.rb +9 -0
  10. data/lib/mws/shipment_invoicing.rb +3 -0
  11. data/lib/mws/shipment_invoicing/client.rb +74 -0
  12. data/lib/peddler/client.rb +18 -15
  13. data/lib/peddler/errors/builder.rb +7 -2
  14. data/lib/peddler/errors/class_generator.rb +7 -2
  15. data/lib/peddler/errors/error.rb +6 -2
  16. data/lib/peddler/errors/parser.rb +1 -1
  17. data/lib/peddler/flat_file_parser.rb +6 -4
  18. data/lib/peddler/headers.rb +53 -1
  19. data/lib/peddler/marketplace.rb +24 -22
  20. data/lib/peddler/operation.rb +17 -11
  21. data/lib/peddler/parser.rb +1 -1
  22. data/lib/peddler/structured_list.rb +1 -1
  23. data/lib/peddler/vcr_matcher.rb +7 -7
  24. data/lib/peddler/version.rb +1 -1
  25. data/lib/peddler/xml_parser.rb +1 -1
  26. data/lib/peddler/xml_response_parser.rb +3 -2
  27. metadata +15 -150
  28. data/lib/mws/off_amazon_payments/client.rb +0 -362
  29. data/lib/mws/reports/parser.rb +0 -35
  30. data/test/credentials.rb +0 -23
  31. data/test/helper.rb +0 -15
  32. data/test/integration/test_errors.rb +0 -25
  33. data/test/integration/test_feeds.rb +0 -37
  34. data/test/integration/test_fulfillment_inbound_shipment.rb +0 -35
  35. data/test/integration/test_fulfillment_inventory.rb +0 -20
  36. data/test/integration/test_fulfillment_outbound_shipment.rb +0 -13
  37. data/test/integration/test_merchant_fulfillment.rb +0 -69
  38. data/test/integration/test_multibyte_queries.rb +0 -17
  39. data/test/integration/test_mws_headers.rb +0 -16
  40. data/test/integration/test_off_amazon_payments.rb +0 -13
  41. data/test/integration/test_orders.rb +0 -30
  42. data/test/integration/test_products.rb +0 -97
  43. data/test/integration/test_recommendations.rb +0 -20
  44. data/test/integration/test_reports.rb +0 -51
  45. data/test/integration/test_sellers.rb +0 -13
  46. data/test/integration/test_subscriptions.rb +0 -27
  47. data/test/integration_helper.rb +0 -53
  48. data/test/mws.yml +0 -36
  49. data/test/mws.yml.example +0 -32
  50. data/test/null_client.rb +0 -25
  51. data/test/recorder.rb +0 -39
  52. data/test/unit/mws/test_feeds_client.rb +0 -103
  53. data/test/unit/mws/test_finances_client.rb +0 -74
  54. data/test/unit/mws/test_fulfillment_inbound_shipment_client.rb +0 -426
  55. data/test/unit/mws/test_fulfillment_inventory_client.rb +0 -48
  56. data/test/unit/mws/test_fulfillment_outbound_shipment_client.rb +0 -202
  57. data/test/unit/mws/test_merchant_fulfillment_client.rb +0 -109
  58. data/test/unit/mws/test_off_amazon_payments_client.rb +0 -286
  59. data/test/unit/mws/test_orders_client.rb +0 -111
  60. data/test/unit/mws/test_products_client.rb +0 -248
  61. data/test/unit/mws/test_recommendations_client.rb +0 -62
  62. data/test/unit/mws/test_reports_client.rb +0 -209
  63. data/test/unit/mws/test_sellers_client.rb +0 -47
  64. data/test/unit/mws/test_subscriptions_client.rb +0 -182
  65. data/test/unit/peddler/errors/test_builder.rb +0 -65
  66. data/test/unit/peddler/errors/test_class_generator.rb +0 -18
  67. data/test/unit/peddler/errors/test_error.rb +0 -33
  68. data/test/unit/peddler/errors/test_parser.rb +0 -44
  69. data/test/unit/peddler/test_client.rb +0 -203
  70. data/test/unit/peddler/test_flat_file_parser.rb +0 -102
  71. data/test/unit/peddler/test_headers.rb +0 -55
  72. data/test/unit/peddler/test_marketplace.rb +0 -47
  73. data/test/unit/peddler/test_operation.rb +0 -87
  74. data/test/unit/peddler/test_parser.rb +0 -36
  75. data/test/unit/peddler/test_structured_list.rb +0 -39
  76. data/test/unit/peddler/test_vcr_matcher.rb +0 -55
  77. data/test/unit/peddler/test_xml_parser.rb +0 -37
  78. data/test/unit/peddler/test_xml_response_parser.rb +0 -39
  79. data/test/unit/test_mws.rb +0 -11
  80. data/test/vcr_cassettes/CartInformation.yml +0 -433
  81. data/test/vcr_cassettes/CustomerInformation.yml +0 -433
  82. data/test/vcr_cassettes/Errors.yml +0 -885
  83. data/test/vcr_cassettes/Feeds.yml +0 -9957
  84. data/test/vcr_cassettes/FulfillmentInboundShipment.yml +0 -6166
  85. data/test/vcr_cassettes/FulfillmentInventory.yml +0 -850
  86. data/test/vcr_cassettes/FulfillmentOutboundShipment.yml +0 -433
  87. data/test/vcr_cassettes/MWSHeaders.yml +0 -2964
  88. data/test/vcr_cassettes/MerchantFulfillment.yml +0 -753
  89. data/test/vcr_cassettes/MultibyteQueries.yml +0 -437
  90. data/test/vcr_cassettes/OffAmazonPayments.yml +0 -433
  91. data/test/vcr_cassettes/Orders.yml +0 -4740
  92. data/test/vcr_cassettes/PeddlerVCRMatcher.yml +0 -41
  93. data/test/vcr_cassettes/Products.yml +0 -7139
  94. data/test/vcr_cassettes/Recommendations.yml +0 -3145
  95. data/test/vcr_cassettes/Reports.yml +0 -5549
  96. data/test/vcr_cassettes/Sellers.yml +0 -433
  97. data/test/vcr_cassettes/Subscriptions.yml +0 -1529
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mws/shipment_invoicing/client'
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'peddler/client'
4
+
5
+ module MWS
6
+ module ShipmentInvoicing
7
+ # With the Shipment Invoicing API section, you can integrate invoicing into
8
+ # Amazon's shipping process for a seller's FBA order.
9
+ #
10
+ # @note This functionality is available only in the Brazil marketplace.
11
+ class Client < ::Peddler::Client
12
+ self.version = '2018-09-01'
13
+ self.path = "/ShipmentInvoicing/#{version}"
14
+
15
+ # Returns the information required to generate an invoice for the shipment
16
+ # of a Fulfillment by Amazon order
17
+ #
18
+ # @see https://docs.developer.amazonservices.com/en_US/shipment_invoicing/ShipmentInvoicing_GetFBAOutboundShipmentDetail.html
19
+ # @param [String] marketplace_id
20
+ # @param [String] amazon_shipment_id
21
+ # @return [Peddler::XMLParser]
22
+ def get_fba_outbound_shipment_detail(marketplace_id, amazon_shipment_id)
23
+ operation('GetFBAOutboundShipmentDetail')
24
+ .add('MarketplaceId' => marketplace_id,
25
+ 'AmazonShipmentId' => amazon_shipment_id)
26
+
27
+ run
28
+ end
29
+
30
+ # Submits shipment invoice data for a given shipment
31
+ #
32
+ # @see https://docs.developer.amazonservices.com/en_US/shipment_invoicing/ShipmentInvoicing_SubmitFBAOutboundShipmentInvoice.html
33
+ # @param [String] marketplace_id
34
+ # @param [String] amazon_shipment_id
35
+ # @param [String] invoice_content
36
+ # @return [Peddler::XMLParser]
37
+ def submit_fba_outbound_shipment_invoice(marketplace_id,
38
+ amazon_shipment_id,
39
+ invoice_content)
40
+ self.body = invoice_content
41
+
42
+ operation('SubmitFBAOutboundShipmentInvoice')
43
+ .add('MarketplaceId' => marketplace_id,
44
+ 'AmazonShipmentId' => amazon_shipment_id)
45
+
46
+ run
47
+ end
48
+
49
+ # Gets the invoice processing status for the shipments that you specify
50
+ #
51
+ # @see https://docs.developer.amazonservices.com/en_US/shipment_invoicing/ShipmentInvoicing_GetFBAOutboundShipmentInvoiceStatus.html
52
+ # @param [String] marketplace_id
53
+ # @param [String] amazon_shipment_id
54
+ # @return [Peddler::XMLParser]
55
+ def get_fba_outbound_shipment_invoice_status(marketplace_id,
56
+ amazon_shipment_id)
57
+ operation('GetFBAOutboundShipmentInvoiceStatus')
58
+ .add('MarketplaceId' => marketplace_id,
59
+ 'AmazonShipmentId' => amazon_shipment_id)
60
+
61
+ run
62
+ end
63
+
64
+ # Gets the operational status of the API
65
+ #
66
+ # @see https://docs.developer.amazonservices.com/en_US/shipment_invoicing/ShipmentInvoicing_GetServiceStatus.html
67
+ # @return [Peddler::XMLParser]
68
+ def get_service_status
69
+ operation('GetServiceStatus')
70
+ run
71
+ end
72
+ end
73
+ end
74
+ end
@@ -16,7 +16,7 @@ module Peddler
16
16
  include Jeff
17
17
 
18
18
  class << self
19
- # @api private
19
+ # @!visibility private
20
20
  attr_accessor :parser, :path, :version
21
21
 
22
22
  private
@@ -52,6 +52,7 @@ module Peddler
52
52
  attr_accessor :auth_token
53
53
 
54
54
  # The seller's Merchant ID
55
+ # @note Amazon also refers to this as Seller ID or Merchant Token
55
56
  # @return [String]
56
57
  attr_accessor :merchant_id
57
58
 
@@ -80,44 +81,44 @@ module Peddler
80
81
  str ? add_content(str) : clear_content!
81
82
  end
82
83
 
83
- # @api private
84
+ # @!visibility private
84
85
  attr_writer :path
85
86
 
86
- # @api private
87
+ # @!visibility private
87
88
  def path
88
89
  @path ||= self.class.path
89
90
  end
90
91
 
91
- # @api private
92
+ # @!visibility private
92
93
  def defaults
93
94
  @defaults ||= { expects: 200 }
94
95
  end
95
96
 
96
- # @api private
97
+ # @!visibility private
97
98
  def headers
98
99
  @headers ||= {}
99
100
  end
100
101
 
101
- # @api private
102
+ # @!visibility private
102
103
  def aws_endpoint
103
104
  "https://#{host}#{path}"
104
105
  end
105
106
 
106
- # @api private
107
+ # @!visibility private
107
108
  def operation(action = nil)
108
109
  action ? @operation = Operation.new(action) : @operation
109
110
  end
110
111
 
111
- # @api private
112
- def run
112
+ # @!visibility private
113
+ def run(&block)
113
114
  opts = build_options
114
- opts.store(:response_block, Proc.new) if block_given?
115
+ opts.store(:response_block, block) if block_given?
115
116
  res = post(opts)
116
117
  self.body = nil if res.status == 200
117
118
 
118
119
  parser.new(res, encoding)
119
- rescue ::Excon::Error::HTTPStatus => error
120
- handle_http_status_error(error)
120
+ rescue ::Excon::Error::HTTPStatus => e
121
+ handle_http_status_error(e)
121
122
  end
122
123
 
123
124
  private
@@ -128,13 +129,15 @@ module Peddler
128
129
  end
129
130
 
130
131
  def add_content(content)
131
- if content.start_with?('<?xml')
132
+ @body = content
133
+ if content.encoding.names.include?('BINARY')
134
+ headers['Content-Type'] = 'application/octet-stream'
135
+ elsif content.start_with?('<?xml')
132
136
  headers['Content-Type'] = 'text/xml'
133
- @body = content
134
137
  else
135
138
  headers['Content-Type'] =
136
139
  "text/tab-separated-values; charset=#{encoding}"
137
- @body = content.encode(encoding)
140
+ @body = @body.encode(encoding)
138
141
  end
139
142
  end
140
143
 
@@ -7,7 +7,7 @@ require 'peddler/errors/parser'
7
7
 
8
8
  module Peddler
9
9
  module Errors
10
- # @api private
10
+ # @!visibility private
11
11
  class Builder
12
12
  extend Forwardable
13
13
 
@@ -28,6 +28,7 @@ module Peddler
28
28
 
29
29
  def build
30
30
  parse_original_response
31
+ return if no_error_response?
31
32
  return if bad_class_name?
32
33
 
33
34
  error_class.new(error_message, error)
@@ -36,7 +37,11 @@ module Peddler
36
37
  private
37
38
 
38
39
  def bad_class_name?
39
- error_name =~ DIGIT_AS_FIRST_CHAR
40
+ error_name.match?(DIGIT_AS_FIRST_CHAR)
41
+ end
42
+
43
+ def no_error_response?
44
+ response.parse.nil?
40
45
  end
41
46
 
42
47
  def error_class
@@ -5,7 +5,7 @@ require 'peddler/errors/error'
5
5
 
6
6
  module Peddler
7
7
  module Errors
8
- # @api private
8
+ # @!visibility private
9
9
  class ClassGenerator
10
10
  include Singleton
11
11
 
@@ -19,7 +19,12 @@ module Peddler
19
19
 
20
20
  def generate(name)
21
21
  with_mutex do
22
- return Errors.const_get(name) if Errors.const_defined?(name)
22
+ if Errors.const_defined?(name)
23
+ error = Errors.const_get(name)
24
+ return error if error <= Error
25
+
26
+ raise TypeError, "#{name} must be a Peddler::Errors::Error"
27
+ end
23
28
 
24
29
  Errors.const_set(name, Class.new(Error))
25
30
  end
@@ -3,11 +3,15 @@
3
3
  require 'forwardable'
4
4
 
5
5
  module Peddler
6
- # @api private
6
+ # @!visibility private
7
7
  module Errors
8
8
  # These error codes are common to all Amazon MWS API sections.
9
9
  #
10
10
  # @see https://docs.developer.amazonservices.com/en_US/dev_guide/DG_Errors.html
11
+ #
12
+ # There are quite a few other error types they do not explicitly document
13
+ # above. I decided not to define any for the sake of consistency and future
14
+ # maintenance.
11
15
  CODES = %w[
12
16
  AccessDenied
13
17
  InputStreamDisconnected
@@ -20,7 +24,7 @@ module Peddler
20
24
  SignatureDoesNotMatch
21
25
  ].freeze
22
26
 
23
- # @api private
27
+ # @!visibility private
24
28
  class Error < StandardError
25
29
  extend Forwardable
26
30
 
@@ -4,7 +4,7 @@ require 'peddler/xml_parser'
4
4
 
5
5
  module Peddler
6
6
  module Errors
7
- # @api private
7
+ # @!visibility private
8
8
  class Parser < XMLParser
9
9
  def message
10
10
  parse['Message']
@@ -6,7 +6,7 @@ require 'digest/md5'
6
6
  require 'peddler/headers'
7
7
 
8
8
  module Peddler
9
- # @api private
9
+ # @!visibility private
10
10
  class FlatFileParser < SimpleDelegator
11
11
  include Headers
12
12
 
@@ -23,7 +23,7 @@ module Peddler
23
23
  end
24
24
 
25
25
  def parse(&blk)
26
- CSV.parse(content, OPTIONS, &blk) unless content.empty?
26
+ CSV.parse(content, **OPTIONS, &blk) unless content.empty?
27
27
  end
28
28
 
29
29
  def records_count
@@ -39,12 +39,14 @@ module Peddler
39
39
  def scrub_body!(encoding)
40
40
  return if body.encoding == Encoding::UTF_8
41
41
 
42
- self.body = body.dup.force_encoding(encoding)
42
+ self.body = body.dup.force_encoding(content_charset || encoding)
43
43
  end
44
44
 
45
45
  def extract_content_and_summary
46
46
  @content = body.encode('UTF-8', invalid: :replace, undef: :replace)
47
- @summary, @content = @content.split("\n\n", 2) if @content =~ /\t\t.*\n\n/
47
+ return unless @content.match?(/\t\t.*\n\n/)
48
+
49
+ @summary, @content = @content.split("\n\n", 2)
48
50
  end
49
51
 
50
52
  def summarize
@@ -1,8 +1,60 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'time'
4
+
3
5
  module Peddler
4
- # Parses MWS-specific headers
6
+ # Parses useful metadata returned in response headers
5
7
  module Headers
8
+ # The size of the response body in bytes
9
+ # @return [String, nil]
10
+ def content_length
11
+ return unless headers['Content-Length']
12
+
13
+ headers['Content-Length'].to_i
14
+ end
15
+
16
+ # The MD5 digest of the response body
17
+ # @return [String, nil]
18
+ def content_md5
19
+ headers['Content-MD5']
20
+ end
21
+
22
+ # The MIME type of the response
23
+ # @return [String, nil]
24
+ def content_media_type
25
+ return unless headers['Content-Type']
26
+
27
+ headers['Content-Type'].split(';').first
28
+ end
29
+
30
+ # The general category into which the MIME type falls
31
+ # @return [String, nil]
32
+ def content_type
33
+ return unless content_media_type
34
+
35
+ content_media_type.split('/').first
36
+ end
37
+
38
+ # The exact kind of data of the specified type the MIME type represents
39
+ # @return [String, nil]
40
+ def content_subtype
41
+ return unless content_media_type
42
+
43
+ content_media_type.split('/').last
44
+ end
45
+
46
+ # The character encoding of the response
47
+ # @return [Encoding, nil]
48
+ def content_charset
49
+ match_data = headers['Content-Type']&.match(/charset=(.*);?/)
50
+ return unless match_data
51
+
52
+ string = match_data[1].upcase
53
+ string = 'UTF-8' if string == 'UTF8'
54
+
55
+ Encoding.find(string)
56
+ end
57
+
6
58
  # The max hourly request quota for the requested operation
7
59
  # @return [Integer, nil]
8
60
  def mws_quota_max
@@ -1,29 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Peddler
4
- # @api private
4
+ # @!visibility private
5
5
  # @see https://docs.developer.amazonservices.com/en_US/dev_guide/DG_Endpoints.html
6
- Marketplace = Struct.new(:id, :country_code, :host) do
6
+ class Marketplace
7
7
  class << self
8
8
  attr_reader :all
9
9
 
10
10
  def find(key)
11
- marketplace = if key.nil?
12
- missing_key!
13
- elsif key.size == 2
14
- find_by_country_code(key)
15
- else
16
- find_by_id(key)
17
- end
11
+ missing_key! unless key
12
+ marketplace = key.size == 2 ? find_by_country(key) : find_by_id(key)
18
13
 
19
14
  marketplace || not_found!(key)
20
15
  end
21
16
 
22
17
  private
23
18
 
24
- def find_by_country_code(country_code)
25
- country_code = 'GB' if country_code == 'UK'
26
- all.find { |marketplace| marketplace.country_code == country_code }
19
+ def find_by_country(code)
20
+ code = 'GB' if code == 'UK'
21
+ all.find { |marketplace| marketplace.country_code == code }
27
22
  end
28
23
 
29
24
  def find_by_id(id)
@@ -39,35 +34,42 @@ module Peddler
39
34
  end
40
35
  end
41
36
 
42
- # Caveat: We use supersets Windows-31J and CP1252 in place of Shift_JIS and
43
- # ISO 8859-1 respectively to handle some edge cases. These should be safe to
44
- # drop in as replacements.
37
+ attr_reader :id, :country_code, :host
38
+
39
+ def initialize(id, country_code, host)
40
+ @id = id
41
+ @country_code = country_code
42
+ @host = host
43
+ end
44
+
45
45
  def encoding
46
46
  case country_code
47
47
  when 'JP'
48
48
  'Windows-31J'
49
- when 'CN'
50
- 'UTF-16'
51
49
  else
52
50
  'CP1252'
53
51
  end
54
52
  end
55
53
 
56
54
  @all = [
55
+ ['A2Q3Y263D00KWC', 'BR', 'mws.amazonservices.com'],
57
56
  ['A2EUQ1WTGCTBG2', 'CA', 'mws.amazonservices.com'],
58
57
  ['A1AM78C64UM0Y8', 'MX', 'mws.amazonservices.com'],
59
58
  ['ATVPDKIKX0DER', 'US', 'mws.amazonservices.com'],
60
- ['A2Q3Y263D00KWC', 'BR', 'mws.amazonservices.com'],
59
+ ['A2VIGQ35RCS4UG', 'AE', 'mws.amazonservices.ae'],
61
60
  ['A1PA6795UKMFR9', 'DE', 'mws-eu.amazonservices.com'],
61
+ ['ARBP9OOSHTCHU', 'EG', 'mws-eu.amazonservices.com'],
62
62
  ['A1RKKUPIHCS9HS', 'ES', 'mws-eu.amazonservices.com'],
63
63
  ['A13V1IB3VIYZZH', 'FR', 'mws-eu.amazonservices.com'],
64
- ['APJ6JRA9NG5V4', 'IT', 'mws-eu.amazonservices.com'],
65
64
  ['A1F83G8C2ARO7P', 'GB', 'mws-eu.amazonservices.com'],
66
- ['A33AVAJ2PDY3EV', 'TR', 'mws-eu.amazonservices.com'],
67
65
  ['A21TJRUUN4KGV', 'IN', 'mws.amazonservices.in'],
66
+ ['APJ6JRA9NG5V4', 'IT', 'mws-eu.amazonservices.com'],
67
+ ['A1805IZSGTT6HS', 'NL', 'mws-eu.amazonservices.com'],
68
+ ['A17E79C6D8DWNP', 'SA', 'mws-eu.amazonservices.com'],
69
+ ['A33AVAJ2PDY3EV', 'TR', 'mws-eu.amazonservices.com'],
70
+ ['A19VAU5U5O7RUS', 'SG', 'mws-fe.amazonservices.com'],
68
71
  ['A39IBJ37TRP1C6', 'AU', 'mws.amazonservices.com.au'],
69
- ['A1VC38T7YXB528', 'JP', 'mws.amazonservices.jp'],
70
- ['AAHKV2X7AFYLW', 'CN', 'mws.amazonservices.com.cn']
72
+ ['A1VC38T7YXB528', 'JP', 'mws.amazonservices.jp']
71
73
  ].map do |values|
72
74
  new(*values)
73
75
  end
@@ -5,7 +5,7 @@ require 'time'
5
5
  require 'peddler/structured_list'
6
6
 
7
7
  module Peddler
8
- # @api private
8
+ # @!visibility private
9
9
  class Operation < SimpleDelegator
10
10
  CAPITAL_LETTERS = /[A-Z]/.freeze
11
11
  ALL_CAPS = %w[sku cod].freeze
@@ -28,15 +28,12 @@ module Peddler
28
28
  self
29
29
  end
30
30
 
31
- def store(key, val, parent: '')
32
- key = camelize(key) if key.is_a?(Symbol)
33
- key = "#{parent}.#{key}" unless parent.empty?
34
-
35
- val = val.iso8601 if val.respond_to?(:iso8601)
36
- val = val.to_h if val.is_a?(Struct)
31
+ def store(key, val, parent = nil)
32
+ key = [parent, camelize(key)].compact.join('.')
33
+ val = format_known_types(val)
37
34
 
38
35
  if val.is_a?(Hash)
39
- val.each { |keyval| store(*keyval, parent: key) }
36
+ val.each { |keyval| store(*keyval, key) }
40
37
  else
41
38
  __getobj__.store(key, val)
42
39
  end
@@ -51,10 +48,11 @@ module Peddler
51
48
 
52
49
  private
53
50
 
54
- def camelize(sym)
55
- return sym.to_s if sym =~ CAPITAL_LETTERS
51
+ def camelize(key)
52
+ return key unless key.is_a?(Symbol)
53
+ return key.to_s if key.match?(CAPITAL_LETTERS)
56
54
 
57
- sym
55
+ key
58
56
  .to_s
59
57
  .split('_')
60
58
  .map { |token| capitalize(token) }
@@ -68,5 +66,13 @@ module Peddler
68
66
  word.capitalize
69
67
  end
70
68
  end
69
+
70
+ def format_known_types(val)
71
+ val = val.utc.iso8601(2) if val.is_a?(Time)
72
+ val = val.iso8601 if val.is_a?(Date)
73
+ val = val.to_h if val.is_a?(Struct)
74
+
75
+ val
76
+ end
71
77
  end
72
78
  end