e_plat 1.4.0 → 1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 43bb902d0393d1fdf55cda97af98daf3e7d671a29ad508c19184b9cf8a1b7fa6
4
- data.tar.gz: 8956828b1e9cfb81caa3b90350460129f245344429a05a8056dd69262abf5b44
3
+ metadata.gz: 1f97875697b04e12d0fd6514ae9198d03022199c064d0c752ffa60a7f024c13e
4
+ data.tar.gz: e8ebc93252048ff24b128d3f46125d6709fccf66dc95578ab5267bb842d0011c
5
5
  SHA512:
6
- metadata.gz: ba32bbdf9786f7897d45298589b5e1f289640c529f04c076cb0cc03bcb2701231d216edde041ade63dab6470a30cac3b58c66e4a64d8648147c9fe5bf9ed3217
7
- data.tar.gz: f3567911feab30badca852ef964bdc9d5e63de310614e2c39d07def9d9e0f1c88ab3171311b1115baa5ff69167776037374b592ea38f153a6b39ed926b05582f
6
+ metadata.gz: 0405d140e821f967cd7266006fd79881b8da73c6fe9bba9e82f337326d5f604392627e7c77e9e399a3a4b278aa8daee2590ca667b2834344e740799acce462a0
7
+ data.tar.gz: 4305d78ed5fb650cd21034bd450c7fca9ed3cdf4af8432202b2dfc888fc1ee2f9ef6c2d97e3a74f7044d110fffc03cd7255e2ac9abdad09b8fbdf7e65e94c2a6
@@ -8,6 +8,7 @@ module EPlat
8
8
  EPlat::Shopify::Product
9
9
  EPlat::Shopify::Product::Variant
10
10
  )
11
+ GRAPHQL_PAGING_PARAMS = %w(after before first last limit).freeze
11
12
 
12
13
  def initialize(parsed = [])
13
14
  super parsed
@@ -56,8 +57,8 @@ module EPlat
56
57
  url = "#{ resource_class.collection_path }#{ url }" if client.bigcommerce?
57
58
 
58
59
  if paginates_via_graphql?
59
- arg_name = (url == @next) ? "after" : "before"
60
- resource_class.find(:all, params: {arg_name => url, first: 100})
60
+ cursor_param = (url == @next) ? "after" : "before"
61
+ resource_class.find(:all, params: params_for_another_graphql_page(cursor_param, url))
61
62
  elsif client.woocommerce?
62
63
  page_number = extract_page_from_url(url)
63
64
  resource_class.find(:all, params: {page: page_number})
@@ -66,6 +67,12 @@ module EPlat
66
67
  end
67
68
  end
68
69
 
70
+ def params_for_another_graphql_page(cursor_param, cursor)
71
+ filter_params = (original_params || {}).to_h.reject { |key, _value| GRAPHQL_PAGING_PARAMS.include?(key.to_s) }
72
+
73
+ filter_params.merge(cursor_param => cursor, first: 100)
74
+ end
75
+
69
76
  def pagination_links
70
77
  return pagination_cursors if paginates_via_graphql?
71
78
 
@@ -10,6 +10,7 @@ module EPlat
10
10
 
11
11
  FILTER_ARGS = [:id, :after, :before, :last, :first, :sort_key, :reverse].freeze
12
12
  QUERY_ARG_ARGS = [:available_for_sale, :created_at, :product_type, :product_id, :tag, :tag_not, :title, :updated_at, :vendor].freeze
13
+ UserErrorsResponse = Struct.new(:body)
13
14
 
14
15
  class_methods do
15
16
 
@@ -64,7 +65,7 @@ module EPlat
64
65
 
65
66
  instantiate_record resources_parsed_from(response)
66
67
  else
67
- instantiate_collection resources_parsed_from(response)
68
+ instantiate_collection resources_parsed_from(response), args
68
69
  end
69
70
  end
70
71
  rescue ActiveResource::ResourceNotFound
@@ -229,6 +230,13 @@ module EPlat
229
230
 
230
231
  end
231
232
 
233
+ def save!
234
+ return true if save
235
+
236
+ invalid_response = UserErrorsResponse.new({message: errors.full_messages.join(", ")}.to_json)
237
+ raise ActiveResource::ResourceInvalid.new(invalid_response)
238
+ end
239
+
232
240
  def mutate_graphql(action, graphql_proc_constant, *args)
233
241
  callback_name = (action == :delete) ? :destroy : action
234
242
 
@@ -239,6 +247,9 @@ module EPlat
239
247
  raise EPlat::GraphqlError.new(response.first["message"])
240
248
  elsif response["errors"]
241
249
  raise EPlat::GraphqlError.new(response["errors"].first["message"])
250
+ elsif (user_errors_by_mutation = user_errors_by_mutation_from(response)).any?
251
+ log_user_errors(user_errors_by_mutation)
252
+ raise_resource_invalid_with(user_errors_by_mutation.values.flatten)
242
253
  else
243
254
  response = remove_mutation_root_from(response, graphql_proc_constant)
244
255
  parsed_response = self.class.resources_parsed_from(response)
@@ -253,6 +264,8 @@ module EPlat
253
264
  changed_attributes.clear
254
265
  end
255
266
  end
267
+ rescue ActiveResource::ResourceInvalid
268
+ raise
256
269
  rescue StandardError => e
257
270
  raise EPlat::GraphqlError.new(e.message)
258
271
  end
@@ -266,6 +279,46 @@ module EPlat
266
279
  mutation_proc.call(input, additional_graphql:)
267
280
  end
268
281
 
282
+ # one request can carry several mutation roots, e.g. productUpdate plus productVariantsBulkUpdate
283
+ def user_errors_by_mutation_from(response)
284
+ data = response["data"].is_a?(Hash) ? response["data"] : response
285
+ mutation_payloads = data.select { |_mutation_name, payload| payload.is_a?(Hash) }
286
+
287
+ mutation_payloads
288
+ .transform_values { |payload| payload["userErrors"] || [] }
289
+ .reject { |_mutation_name, user_errors| user_errors.empty? }
290
+ end
291
+
292
+ def log_user_errors(user_errors_by_mutation)
293
+ user_errors_by_mutation.each do |mutation_name, user_errors|
294
+ user_errors_logger&.warn(
295
+ "[EPlat] #{mutation_name} userErrors on #{self.class.name} #{id.inspect}: #{user_errors_message(user_errors)}"
296
+ )
297
+ end
298
+ end
299
+
300
+ def user_errors_logger
301
+ defined?(Rails) && Rails.logger ? Rails.logger : self.class.logger
302
+ end
303
+
304
+ def user_errors_message(user_errors)
305
+ user_errors.map do |user_error|
306
+ field = Array(user_error["field"]).join(".")
307
+
308
+ [field.presence, user_error["message"]].compact.join(": ")
309
+ end.join(", ")
310
+ end
311
+
312
+ # ActiveResource's save rescues ResourceInvalid into errors and returns false; save! re-raises it
313
+ def raise_resource_invalid_with(user_errors)
314
+ error_messages = user_errors.map { |user_error| user_error["message"] }
315
+ invalid_response = UserErrorsResponse.new(
316
+ {errors: {base: error_messages}, message: error_messages.join(", ")}.to_json
317
+ )
318
+
319
+ raise ActiveResource::ResourceInvalid.new(invalid_response)
320
+ end
321
+
269
322
  def remove_mutation_root_from(data, graphql_proc_constant)
270
323
  mutation_root = graphql_proc_constant.split(".").last.camelcase(:lower)
271
324
  (mutation_root && data[mutation_root]) ? data[mutation_root] : data
@@ -47,6 +47,10 @@ module EPlat::Shopify::GraphQL::V202604::Mutation::Product::Variant
47
47
  mutation {
48
48
  #{additional_graphql}
49
49
  productVariantsBulkDelete(#{args}) {
50
+ userErrors {
51
+ field
52
+ message
53
+ }
50
54
  product {
51
55
  id
52
56
  }
@@ -61,6 +65,10 @@ module EPlat::Shopify::GraphQL::V202604::Mutation::Product::Variant
61
65
  <<~GRAPHQL
62
66
  #{additional_graphql}
63
67
  productVariantsBulkCreate(#{args}) {
68
+ userErrors {
69
+ field
70
+ message
71
+ }
64
72
  productVariants {
65
73
  #{EPlat::Shopify::Product::Variant.graphql_fields}
66
74
  }
@@ -74,6 +82,10 @@ module EPlat::Shopify::GraphQL::V202604::Mutation::Product::Variant
74
82
  <<~GRAPHQL
75
83
  #{additional_graphql}
76
84
  productVariantsBulkUpdate(#{args}) {
85
+ userErrors {
86
+ field
87
+ message
88
+ }
77
89
  productVariants {
78
90
  #{EPlat::Shopify::Product::Variant.graphql_fields}
79
91
  }
@@ -10,6 +10,10 @@ module EPlat::Shopify::GraphQL::V202604::Mutation::Product
10
10
  mutation {
11
11
  #{additional_graphql}
12
12
  productCreate(#{args}) {
13
+ userErrors {
14
+ field
15
+ message
16
+ }
13
17
  product {
14
18
  #{EPlat::Shopify::Product.graphql_fields}
15
19
  }
@@ -25,6 +29,10 @@ module EPlat::Shopify::GraphQL::V202604::Mutation::Product
25
29
  mutation {
26
30
  #{additional_graphql}
27
31
  productUpdate(#{args}) {
32
+ userErrors {
33
+ field
34
+ message
35
+ }
28
36
  product {
29
37
  #{EPlat::Shopify::Product.graphql_fields}
30
38
  }
@@ -1,3 +1,3 @@
1
1
  module EPlat
2
- VERSION = "1.4.0"
2
+ VERSION = "1.5.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: e_plat
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - oliwoodsuk