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.
- checksums.yaml +4 -4
- data/README.md +7 -7
- data/lib/e_plat/mapping/shopify/v_2026_10/metafield.rb +26 -0
- data/lib/e_plat/mapping/shopify/v_2026_10/order/billing_address.rb +14 -0
- data/lib/e_plat/mapping/shopify/v_2026_10/order/shipping_address.rb +30 -0
- data/lib/e_plat/mapping/shopify/v_2026_10/order.rb +26 -0
- data/lib/e_plat/mapping/shopify/v_2026_10/product/image.rb +52 -0
- data/lib/e_plat/mapping/shopify/v_2026_10/product/option.rb +45 -0
- data/lib/e_plat/mapping/shopify/v_2026_10/product/variant/option_value.rb +58 -0
- data/lib/e_plat/mapping/shopify/v_2026_10/product/variant.rb +179 -0
- data/lib/e_plat/mapping/shopify/v_2026_10/product.rb +100 -0
- data/lib/e_plat/mapping/shopify/v_2026_10/script_tag.rb +26 -0
- data/lib/e_plat/mapping/shopify/v_2026_10/shop.rb +26 -0
- data/lib/e_plat/mapping/shopify/v_2026_10/webhook.rb +29 -0
- data/lib/e_plat/resource/collection.rb +9 -2
- data/lib/e_plat/resource/concerns/graph_q_lable.rb +54 -1
- data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_04/mutation/product/variant.rb +12 -0
- data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_04/mutation/product.rb +8 -0
- data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/input/product/variant.rb +84 -0
- data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/input/product/variants_bulk.rb +56 -0
- data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/input/product.rb +36 -0
- data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/input.rb +133 -0
- data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/mutation/product/variant.rb +98 -0
- data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/mutation/product.rb +63 -0
- data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/mutation.rb +5 -0
- data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/query/product/variant.rb +44 -0
- data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/query/product.rb +58 -0
- data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/query.rb +5 -0
- data/lib/e_plat/resource/platform_specific/shopify/product/variant.rb +6 -1
- data/lib/e_plat/version.rb +1 -1
- data/lib/e_plat.rb +2 -2
- 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
|
-
|
|
60
|
-
resource_class.find(:all, params:
|
|
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
|
data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_04/mutation/product/variant.rb
CHANGED
|
@@ -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
|
}
|
data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/input/product/variant.rb
ADDED
|
@@ -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
|
+
#
|
data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/mutation/product/variant.rb
ADDED
|
@@ -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
|
data/lib/e_plat/resource/platform_specific/shopify/graph_q_l/v_2026_10/query/product/variant.rb
ADDED
|
@@ -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
|