shopify_graphql 2.0.1 → 2.2.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: cb945b9c83cd848d26c0776a801f905edae8eca4e39ce8bc3c0e6dbd11d9d621
4
- data.tar.gz: e0a97f24d9fa501a73187d81ecdabe68de614bce10a5bbbc65c1dd7f5b5bc6c0
3
+ metadata.gz: 676b35a53c5124709bcb8760437d53e16678bfae111ddb757036df4c07d01fa0
4
+ data.tar.gz: a32e7e86b6bb543e27d234098225a399e6f38e49e330f7d871f51547943a9eeb
5
5
  SHA512:
6
- metadata.gz: 2181d36cb07500305b03cb6846d1c605b6d56e564914074dd562ea3485c9cc88020433b29aa803ec9a4acd278c65d2eab96bc1ea7c10f0db5d218ecc2e93d177
7
- data.tar.gz: ec238e18c338f1ab644addf84e60bda19a71aa467e8af19f611c0dbab05fb970bdf4d6b240489886c7ba025ffba424b2edf5aa9e5803d194e7ada5355642fb8b
6
+ metadata.gz: c0f3ee5179384954a776d2afecc37a5377c123aecc99b352deb02fb71493792d911356c8a2a950ff9279cfaca0e39c2122d4f002e72ed43dee2e6e0e6e10de0b
7
+ data.tar.gz: ef42df04753e9acd8b3f7b37cddb4c35195dc443fd67300ff5fdbc69487602e3f7dcbda0f5b49f92af52272ac7e56a3db070b9dcff9914753639f3f4d9c07fc9
data/README.md CHANGED
@@ -86,6 +86,68 @@ puts product.title
86
86
  ```
87
87
  </details>
88
88
 
89
+ ### Query with custom headers
90
+
91
+ <details><summary>Click to expand</summary>
92
+ You can pass custom headers to any GraphQL query or mutation by using the `headers` parameter. A common use case is setting the `Accept-Language` header to retrieve content in specific languages:
93
+
94
+ ```rb
95
+ # Pass custom headers to a direct GraphQL call to get French content
96
+ response = ShopifyGraphql.execute(QUERY, headers: { "Accept-Language" => "fr" })
97
+
98
+ # Or create a language-aware query wrapper
99
+ class GetProduct
100
+ include ShopifyGraphql::Query
101
+
102
+ QUERY = <<~GRAPHQL
103
+ query($id: ID!) {
104
+ product(id: $id) {
105
+ id
106
+ title
107
+ description
108
+ seo {
109
+ title
110
+ description
111
+ }
112
+ }
113
+ }
114
+ GRAPHQL
115
+
116
+ def call(id:, language: nil)
117
+ headers = language ? { "Accept-Language" => language } : nil
118
+ response = execute(QUERY, headers: headers, id: id)
119
+ response.data = response.data.product
120
+ response
121
+ end
122
+ end
123
+
124
+ # Then use it to get content in different languages
125
+ french_product = GetProduct.call(
126
+ id: "gid://shopify/Product/12345",
127
+ language: "fr"
128
+ ).data
129
+
130
+ puts french_product.title # => "Le Produit"
131
+ puts french_product.description # => "Description en français"
132
+
133
+ # Get content in Japanese
134
+ japanese_product = GetProduct.call(
135
+ id: "gid://shopify/Product/12345",
136
+ language: "ja"
137
+ ).data
138
+
139
+ puts japanese_product.title # => "商品名"
140
+ puts japanese_product.description # => "商品の説明"
141
+ ```
142
+
143
+ The `Accept-Language` header tells Shopify which language to return the content in. This is particularly useful for:
144
+ - Retrieving translated content for products, collections, and pages
145
+ - Building multi-language storefronts
146
+ - Showing localized SEO content
147
+
148
+ You can also use custom headers for other purposes like passing metadata or context with your GraphQL requests.
149
+ </details>
150
+
89
151
  ### Query with data parsing
90
152
 
91
153
  <details><summary>Click to expand</summary>
@@ -10,6 +10,7 @@ module ShopifyGraphql
10
10
  status
11
11
  }
12
12
  userErrors {
13
+ code
13
14
  field
14
15
  message
15
16
  }
@@ -10,6 +10,7 @@ module ShopifyGraphql
10
10
  status
11
11
  }
12
12
  userErrors {
13
+ code
13
14
  field
14
15
  message
15
16
  }
@@ -13,6 +13,8 @@ module ShopifyGraphql
13
13
  completedAt
14
14
  fileSize
15
15
  url
16
+ objectCount
17
+ rootObjectCount
16
18
  }
17
19
  }
18
20
  }
@@ -37,7 +39,9 @@ module ShopifyGraphql
37
39
  error_code: data.errorCode,
38
40
  created_at: Time.find_zone("UTC").parse(data.createdAt),
39
41
  completed_at: data.completedAt ? Time.find_zone("UTC").parse(data.completedAt) : nil,
40
- url: data.url
42
+ url: data.url,
43
+ object_count: data.objectCount.to_i,
44
+ root_object_count: data.rootObjectCount.to_i,
41
45
  )
42
46
  end
43
47
  end
@@ -29,8 +29,8 @@ module ShopifyGraphql
29
29
  @client ||= ShopifyAPI::Clients::Graphql::Admin.new(session: ShopifyAPI::Context.active_session)
30
30
  end
31
31
 
32
- def execute(query, **variables)
33
- response = client.query(query: query, variables: variables)
32
+ def execute(query, headers: nil, **variables)
33
+ response = client.query(query: query, variables: variables, headers: headers)
34
34
  Response.new(handle_response(response))
35
35
  rescue ShopifyAPI::Errors::HttpResponseError => e
36
36
  Response.new(handle_response(e.response, e))
@@ -114,6 +114,8 @@ module ShopifyGraphql
114
114
  ConnectionError.new(response: response)
115
115
  end
116
116
  exception.error_code = error_code
117
+ exception.error_codes = [ error_code ]
118
+ exception.messages = [ error.message ]
117
119
  raise exception, error_message
118
120
  end
119
121
 
@@ -121,27 +123,52 @@ module ShopifyGraphql
121
123
  return response if response.userErrors.blank?
122
124
 
123
125
  error = response.userErrors.first
124
- error_code = error.code
125
- error_message = generate_error_message(
126
- message: error.message,
127
- code: error_code,
128
- fields: error.field,
126
+ errors = response.userErrors
127
+ error_message = generate_user_errors_message(
128
+ messages: errors.map(&:message),
129
+ codes: errors.map(&:code),
130
+ fields: errors.map(&:field),
129
131
  )
130
132
 
131
133
  exception = UserError.new(response: response)
132
- exception.error_code = error_code
133
- exception.fields = error.field
134
+ exception.error_code = error.code
135
+ exception.error_codes = errors.map(&:code)
136
+ exception.fields = errors.map(&:field)
137
+ exception.messages = errors.map(&:message)
134
138
  raise exception, error_message
135
139
  end
136
140
 
137
- def generate_error_message(message: nil, code: nil, doc: nil, fields: nil)
141
+ def generate_error_message(message: nil, code: nil, doc: nil)
138
142
  string = "Failed.".dup
139
143
  string << " Response code = #{code}." if code
140
144
  string << " Response message = #{message}.".gsub("..", ".") if message
141
145
  string << " Documentation = #{doc}." if doc
142
- string << " Fields = #{fields}." if fields
143
146
  string
144
147
  end
148
+
149
+ def generate_user_errors_message(messages: nil, codes: nil, fields: [])
150
+ if fields.any?
151
+ field_count = fields.size
152
+ result = ["#{field_count} #{"field".pluralize(field_count)} have failed:"]
153
+
154
+ fields.each.with_index do |field, index|
155
+ field_details = ["\n-"]
156
+ field_details << "Response code = #{codes[index]}." if codes&.at(index)
157
+ field_details << "Response message = #{messages[index]}.".gsub("..", ".") if messages&.at(index)
158
+ field_details << "Field = #{field}." if field
159
+
160
+ result << field_details.join(" ")
161
+ end
162
+
163
+ result.join("\n")
164
+ else
165
+ result = ["Failed."]
166
+ result << "Response code = #{codes.join(", ")}." if codes&.any?
167
+ result << "Response message = #{messages&.join(", ")}.".gsub("..", ".") if messages&.any?
168
+
169
+ result.join(" ")
170
+ end
171
+ end
145
172
  end
146
173
 
147
174
  class << self
@@ -1,6 +1,6 @@
1
1
  module ShopifyGraphql
2
2
  class ConnectionError < ShopifyAPI::Errors::HttpResponseError
3
- attr_accessor :error_code, :fields
3
+ attr_accessor :error_code, :error_codes, :fields, :messages
4
4
 
5
5
  def initialize(response: nil)
6
6
  unless response
@@ -1,3 +1,3 @@
1
1
  module ShopifyGraphql
2
- VERSION = "2.0.1"
2
+ VERSION = "2.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shopify_graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kirill Platonov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-01-30 00:00:00.000000000 Z
11
+ date: 2025-05-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails