e_plat 1.4.0 → 1.6.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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +7 -7
  3. data/lib/e_plat/mapping/shopify/v_2026_10/metafield.rb +26 -0
  4. data/lib/e_plat/mapping/shopify/v_2026_10/order/billing_address.rb +14 -0
  5. data/lib/e_plat/mapping/shopify/v_2026_10/order/shipping_address.rb +30 -0
  6. data/lib/e_plat/mapping/shopify/v_2026_10/order.rb +26 -0
  7. data/lib/e_plat/mapping/shopify/v_2026_10/product/image.rb +52 -0
  8. data/lib/e_plat/mapping/shopify/v_2026_10/product/option.rb +45 -0
  9. data/lib/e_plat/mapping/shopify/v_2026_10/product/variant/option_value.rb +58 -0
  10. data/lib/e_plat/mapping/shopify/v_2026_10/product/variant.rb +179 -0
  11. data/lib/e_plat/mapping/shopify/v_2026_10/product.rb +100 -0
  12. data/lib/e_plat/mapping/shopify/v_2026_10/script_tag.rb +26 -0
  13. data/lib/e_plat/mapping/shopify/v_2026_10/shop.rb +26 -0
  14. data/lib/e_plat/mapping/shopify/v_2026_10/webhook.rb +29 -0
  15. data/lib/e_plat/resource/collection.rb +9 -2
  16. data/lib/e_plat/resource/concerns/graph_q_lable.rb +54 -1
  17. data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_04/mutation/product/variant.rb +12 -0
  18. data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_04/mutation/product.rb +8 -0
  19. data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/input/product/variant.rb +84 -0
  20. data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/input/product/variants_bulk.rb +56 -0
  21. data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/input/product.rb +36 -0
  22. data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/input.rb +133 -0
  23. data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/mutation/product/variant.rb +98 -0
  24. data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/mutation/product.rb +63 -0
  25. data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/mutation.rb +5 -0
  26. data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/query/product/variant.rb +44 -0
  27. data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/query/product.rb +58 -0
  28. data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/query.rb +5 -0
  29. data/lib/e_plat/resource/platform_specific/shopify/product/variant.rb +6 -1
  30. data/lib/e_plat/version.rb +1 -1
  31. data/lib/e_plat.rb +2 -2
  32. metadata +23 -1
@@ -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
  }
@@ -0,0 +1,84 @@
1
+ class EPlat::Shopify::GraphQL::V202610::Input::Product::Variant < EPlat::Shopify::GraphQL::V202610::Input
2
+ USES_ELEMENT_NAME_AS_INPUT_ROOT_KEY = false
3
+
4
+ SUPPORTED_FIELDS = %w[
5
+ compareAtPrice
6
+ id
7
+ inventoryItem
8
+ inventoryPolicy
9
+ inventoryQuantities
10
+ mediaSrc
11
+ metafields
12
+ optionValues
13
+ price
14
+ taxable
15
+ ].freeze
16
+
17
+ SUPPORTED_NAMED_ARGUMENT_FIELDS = {
18
+ product_id: %w[
19
+ productId
20
+ ],
21
+ variant: %w[
22
+ compareAtPrice
23
+ id
24
+ inventoryItem
25
+ inventoryPolicy
26
+ inventoryQuantities
27
+ mediaSrc
28
+ metafields
29
+ optionValues
30
+ price
31
+ taxable
32
+ ],
33
+ variants: %w[
34
+ compareAtPrice
35
+ id
36
+ inventoryItem
37
+ inventoryPolicy
38
+ inventoryQuantities
39
+ mediaSrc
40
+ metafields
41
+ optionValues
42
+ price
43
+ taxable
44
+ ],
45
+ inventory_item: %w[
46
+ cost
47
+ countryCodeOfOrigin
48
+ countryHarmonizedSystemCodes
49
+ harmonizedSystemCode
50
+ measurement
51
+ provinceCodeOfOrigin
52
+ requiresShipping
53
+ sku
54
+ tracked
55
+ ],
56
+ option_values: %w[
57
+ optionId
58
+ name
59
+ linkedMetafieldValue
60
+ optionId
61
+ optionName
62
+ ]
63
+ }.with_indifferent_access.freeze
64
+
65
+
66
+ def self.mutation_input(resource, action)
67
+ case action.to_sym
68
+ when :delete
69
+ new(
70
+ variantsIds: [resource.formatted_id],
71
+ product_id: EPlat::Product.formatted_id(resource.product_id)
72
+ )
73
+ else
74
+ new(
75
+ variants: [
76
+ resource.class.mapping.via_native_attributes_where_possible(
77
+ resource.class.remove_root_from(resource.as_json)
78
+ )
79
+ ],
80
+ product_id: EPlat::Product.formatted_id(resource.product_id)
81
+ )
82
+ end.query_input
83
+ end
84
+ end
@@ -0,0 +1,56 @@
1
+ class EPlat::Shopify::GraphQL::V202610::Input::Product::VariantsBulk < EPlat::Shopify::GraphQL::V202610::Input
2
+ USES_ELEMENT_NAME_AS_INPUT_ROOT_KEY = false
3
+
4
+ SUPPORTED_FIELDS = %w[
5
+ compareAtPrice
6
+ id
7
+ inventoryItem
8
+ inventoryPolicy
9
+ inventoryQuantities
10
+ mediaSrc
11
+ metafields
12
+ optionValues
13
+ price
14
+ taxable
15
+ ].freeze
16
+
17
+ SUPPORTED_NAMED_ARGUMENT_FIELDS = {
18
+ variants: %w[
19
+ compareAtPrice
20
+ id
21
+ inventoryItem
22
+ inventoryPolicy
23
+ inventoryQuantities
24
+ mediaSrc
25
+ metafields
26
+ optionValues
27
+ price
28
+ taxable
29
+ ],
30
+ inventory_item: %w[
31
+ cost
32
+ countryCodeOfOrigin
33
+ countryHarmonizedSystemCodes
34
+ harmonizedSystemCode
35
+ measurement
36
+ provinceCodeOfOrigin
37
+ requiresShipping
38
+ sku
39
+ tracked
40
+ ],
41
+ option_values: %w[
42
+ name
43
+ optionId
44
+ linkedMetafieldValue
45
+ optionId
46
+ optionName
47
+ ]
48
+ }.with_indifferent_access.freeze
49
+
50
+ def self.mutation_input(product, action)
51
+ new(
52
+ product_id: EPlat::Product.formatted_id(product.id),
53
+ variants: product.as_json["product"]["variants"]
54
+ ).query_input
55
+ end
56
+ end
@@ -0,0 +1,36 @@
1
+ class EPlat::Shopify::GraphQL::V202610::Input::Product < EPlat::Shopify::GraphQL::V202610::Input
2
+
3
+ SUPPORTED_FIELDS = %w[
4
+ category
5
+ claimOwnership
6
+ title
7
+ descriptionHtml
8
+ productType
9
+ vendor
10
+ tags
11
+ collectionsToJoin
12
+ collectionsToLeave
13
+ combinedListingRole
14
+ metafields
15
+ productOptions
16
+ templateSuffix
17
+ requiresSellingPlan
18
+ giftCard
19
+ giftCardTemplateSuffix
20
+ seo
21
+ status
22
+ id
23
+ handle
24
+ redirectNewHandle
25
+ ].freeze
26
+
27
+ def self.mutation_input(resource, action)
28
+ case action.to_sym
29
+ when :delete
30
+ new(input: {id: resource.formatted_id})
31
+ else
32
+ rootless_json = resource.class.remove_root_from(resource.as_json)
33
+ new(resource.class.mapping.via_native_attributes_where_possible rootless_json)
34
+ end.query_input
35
+ end
36
+ end
@@ -0,0 +1,133 @@
1
+ class EPlat::Shopify::GraphQL::V202610::Input
2
+ attr_accessor :input, :named_arguments
3
+
4
+ SUPPORTED_FIELDS = []
5
+ SUPPORTED_NAMED_ARGUMENT_FIELDS = {}
6
+ USES_ELEMENT_NAME_AS_INPUT_ROOT_KEY = true
7
+
8
+ def initialize(input = {}, **named_arguments)
9
+ @input = input.deep_transform_keys { |key| key.to_s.camelize(:lower) }
10
+ @named_arguments = named_arguments.deep_transform_keys { |key| key.to_s.camelize(:lower) }
11
+ end
12
+
13
+ def query_input
14
+ args =
15
+ if named_arguments.present?
16
+ named_arguments_with_allowed_fields(named_arguments)
17
+ else
18
+ self.class::USES_ELEMENT_NAME_AS_INPUT_ROOT_KEY ? { element_name => allowed_fields } : allowed_fields
19
+ end
20
+
21
+ format_graphql_args(args)
22
+ end
23
+
24
+ def self.mutation_input(resource, action)
25
+ raise "mutation_input not implemented for #{self.class.name}"
26
+ # example:
27
+ # case action.to_sym
28
+ # when :delete
29
+ # new(input: { id: resource.formatted_id })
30
+ # else
31
+ # new(resource.class.mapping.via_native_attributes_where_possible(
32
+ # resource.class.remove_root_from(resource.as_json)
33
+ # ))
34
+ # end.query_input
35
+ end
36
+
37
+
38
+ protected
39
+
40
+ def allowed_fields
41
+ fields_hash = input.slice(*self.class::SUPPORTED_FIELDS)
42
+
43
+ fields_hash.map do |key, value|
44
+ if value.is_a?(Hash) && child_allowed_fields = self.class::SUPPORTED_NAMED_ARGUMENT_FIELDS[key] || self.class::SUPPORTED_NAMED_ARGUMENT_FIELDS[key&.underscore]
45
+ [key, value.slice(*child_allowed_fields)]
46
+ else
47
+ [key, value]
48
+ end
49
+ end.to_h
50
+ end
51
+
52
+ def named_arguments_with_allowed_fields(arguments, name=nil)
53
+ arguments.map do |key, value|
54
+ fields_hash = self.class::SUPPORTED_NAMED_ARGUMENT_FIELDS[name] || self.class::SUPPORTED_NAMED_ARGUMENT_FIELDS[key] || self.class::SUPPORTED_NAMED_ARGUMENT_FIELDS[key&.underscore] || []
55
+
56
+ case value
57
+ when Hash
58
+ [key, named_arguments_with_allowed_fields(value, key.underscore)]
59
+ when Array
60
+ [key, value.map {_1.is_a?(Hash) ? named_arguments_with_allowed_fields(_1, key.underscore) : _1}]
61
+ else
62
+ (fields_hash.empty? || fields_hash.include?(key)) ? [key, value] : [nil, nil]
63
+ end
64
+ end.to_h.compact_blank
65
+ end
66
+
67
+ def format_graphql_item(item, key: nil)
68
+ case item
69
+ when Hash
70
+ "{ #{item.map { |k, v| "#{k}: #{v.is_a?(String) ? enum_friendly(v, key: k) : format_graphql_item(v, key: k)}" }.join(', ')} }"
71
+ when Array
72
+ "[ #{item.map { |i| format_graphql_item(i, key: key) }.join(', ')} ]"
73
+ else
74
+ enum_friendly(item, key: key)
75
+ end
76
+ end
77
+
78
+ def enum_friendly(value, key: nil)
79
+ case
80
+ when key == "tags"
81
+ "\"#{single_quotes_only(value)}\""
82
+ when value.is_a?(String)
83
+ if value.match?(/\A[A-Z_]+\z/)
84
+ value
85
+ else
86
+ "\"#{single_quotes_only(value)}\""
87
+ end
88
+ else
89
+ value
90
+ end
91
+ end
92
+
93
+ def single_quotes_only(value)
94
+ value&.gsub("\"", "'")
95
+ end
96
+
97
+ def format_graphql_args(args, key: nil)
98
+ args.map do |key, value|
99
+ case value
100
+ when Hash
101
+ "#{key}: { #{format_graphql_args(value, key:)} }"
102
+ when Array
103
+ if (value.first.is_a? Hash)
104
+ "#{key}: [ #{value.map { |v| "{ #{format_graphql_args(v, key:)} }" }.join(', ')} ]"
105
+ else
106
+ "#{key}: [ #{value.map { |v| enum_friendly(v, key: key) }.join(', ')} ]"
107
+ end
108
+ when String
109
+ "#{key}: #{enum_friendly(value, key: key)}"
110
+ else
111
+ "#{key}: #{value}"
112
+ end
113
+ end.join(', ')
114
+ end
115
+
116
+ def element_name
117
+ self.class.name.split("::").last.downcase
118
+ end
119
+
120
+ end
121
+ #
122
+ # creates a graphql mutation input.
123
+ # if just input as arg, use:
124
+ # input.new(
125
+ # [{...}, {...}]
126
+ # ).to_graphql_args
127
+ #
128
+ # Otherwise, you can pass named arguments in for each graphql argument:
129
+ # input.new(
130
+ # product_id: "gid/123",
131
+ # variants: [{...}, {...}]
132
+ # ).to_graphql_args
133
+ #
@@ -0,0 +1,98 @@
1
+
2
+ module EPlat::Shopify::GraphQL::V202610::Mutation::Product::Variant
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+
7
+ # def self.product_variant_delete
8
+ # ->(args, additional_graphql: nil) do
9
+ # <<~GRAPHQL
10
+ # mutation {
11
+ # #{additional_graphql}
12
+ # productVariantDelete(#{args}) {
13
+ # deletedProductVariantId
14
+ # userErrors {
15
+ # field
16
+ # message
17
+ # }
18
+ # }
19
+ # }
20
+ # GRAPHQL
21
+ # end
22
+ # end
23
+
24
+ def self.product_variants_bulk_update
25
+ ->(args, additional_graphql: nil) do
26
+ <<~GRAPHQL
27
+ mutation {
28
+ #{product_variants_bulk_update_fragment.call(args, additional_graphql: additional_graphql)}
29
+ }
30
+ GRAPHQL
31
+ end
32
+ end
33
+
34
+ def self.product_variants_bulk_create
35
+ ->(args, additional_graphql: nil) do
36
+ <<~GRAPHQL
37
+ mutation {
38
+ #{product_variants_bulk_create_fragment.call(args, additional_graphql: additional_graphql)}
39
+ }
40
+ GRAPHQL
41
+ end
42
+ end
43
+
44
+ def self.product_variants_bulk_delete
45
+ ->(args, additional_graphql: nil) do
46
+ <<~GRAPHQL
47
+ mutation {
48
+ #{additional_graphql}
49
+ productVariantsBulkDelete(#{args}) {
50
+ userErrors {
51
+ field
52
+ message
53
+ }
54
+ product {
55
+ id
56
+ }
57
+ }
58
+ }
59
+ GRAPHQL
60
+ end
61
+ end
62
+
63
+ def self.product_variants_bulk_create_fragment
64
+ ->(args, additional_graphql: nil) do
65
+ <<~GRAPHQL
66
+ #{additional_graphql}
67
+ productVariantsBulkCreate(#{args}) {
68
+ userErrors {
69
+ field
70
+ message
71
+ }
72
+ productVariants {
73
+ #{EPlat::Shopify::Product::Variant.graphql_fields}
74
+ }
75
+ }
76
+ GRAPHQL
77
+ end
78
+ end
79
+
80
+ def self.product_variants_bulk_update_fragment
81
+ ->(args, additional_graphql: nil) do
82
+ <<~GRAPHQL
83
+ #{additional_graphql}
84
+ productVariantsBulkUpdate(#{args}) {
85
+ userErrors {
86
+ field
87
+ message
88
+ }
89
+ productVariants {
90
+ #{EPlat::Shopify::Product::Variant.graphql_fields}
91
+ }
92
+ }
93
+ GRAPHQL
94
+ end
95
+ end
96
+
97
+ end
98
+ end
@@ -0,0 +1,63 @@
1
+
2
+ module EPlat::Shopify::GraphQL::V202610::Mutation::Product
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+
7
+ def self.product_create
8
+ ->(args, additional_graphql: nil) do
9
+ <<~GRAPHQL
10
+ mutation {
11
+ #{additional_graphql}
12
+ productCreate(#{args}) {
13
+ userErrors {
14
+ field
15
+ message
16
+ }
17
+ product {
18
+ #{EPlat::Shopify::Product.graphql_fields}
19
+ }
20
+ }
21
+ }
22
+ GRAPHQL
23
+ end
24
+ end
25
+
26
+ def self.product_update
27
+ ->(args, additional_graphql: nil) do
28
+ <<~GRAPHQL
29
+ mutation {
30
+ #{additional_graphql}
31
+ productUpdate(#{args}) {
32
+ userErrors {
33
+ field
34
+ message
35
+ }
36
+ product {
37
+ #{EPlat::Shopify::Product.graphql_fields}
38
+ }
39
+ }
40
+ }
41
+ GRAPHQL
42
+ end
43
+ end
44
+
45
+ def self.product_delete
46
+ ->(args, additional_graphql: nil) do
47
+ <<~GRAPHQL
48
+ mutation {
49
+ #{additional_graphql}
50
+ productDelete(#{args}) {
51
+ deletedProductId
52
+ userErrors {
53
+ field
54
+ message
55
+ }
56
+ }
57
+ }
58
+ GRAPHQL
59
+ end
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,5 @@
1
+ class EPlat::Shopify::GraphQL::V202610::Mutation
2
+ include Product, Product::Variant
3
+ end
4
+
5
+
@@ -0,0 +1,44 @@
1
+
2
+ module EPlat::Shopify::GraphQL::V202610::Query::Product::Variant
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+
7
+ def self.variants
8
+ ->(args) do
9
+ formatted_args = args.present? ? "(#{args})" : ""
10
+
11
+ <<~GRAPHQL
12
+ query getProductVariants {
13
+ productVariants#{formatted_args} {
14
+ nodes {
15
+ #{EPlat::Shopify::Product::Variant.graphql_fields}
16
+ }
17
+ pageInfo {
18
+ endCursor
19
+ startCursor
20
+ hasNextPage
21
+ hasPreviousPage
22
+ }
23
+ }
24
+ }
25
+ GRAPHQL
26
+ end
27
+ end
28
+
29
+ def self.variant
30
+ ->(args) do
31
+ formatted_args = args.present? ? "(#{args})" : ""
32
+
33
+ <<~GRAPHQL
34
+ query getProductVariant {
35
+ productVariant#{formatted_args} {
36
+ #{EPlat::Shopify::Product::Variant.graphql_fields}
37
+ }
38
+ }
39
+ GRAPHQL
40
+ end
41
+ end
42
+
43
+ end
44
+ end