shopify_api-graphql-tiny 1.0.1 → 1.0.2

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: 5e48648295daa6495ff73f0415253f062439c876620351d00b90da3ec98ba700
4
- data.tar.gz: 6789cbc730bc6f98f8ac89d63f1a9b57b043a990c685250f3992e8e4756f8a26
3
+ metadata.gz: 18495ff517670050b05536c1ef5fda702e689a4ffab229eba78fd2aba055dce5
4
+ data.tar.gz: c374cf2ae48b8ed7de70b5ec8501841593535ad21ef2d5591deb17c7dc96fdef
5
5
  SHA512:
6
- metadata.gz: e22a8f947de401a3e8ca218486d5ac9e6c396b091d848d189b3564790b4f1b2dcca3e3b32f651698cee5030908ec1aa3926df31c013153b407cb0b466a8624ba
7
- data.tar.gz: 313dc8dcb7058042be6b39240f5177123bd4498d8ddae770801324875e187b5b625246f49b34e1b62ca2b87c0d94d51156a5ecf43b8829e0fcc7ab5378d5c735
6
+ metadata.gz: 3388c846e2190e5996f780bf847d28f66c9336e0a96d53a8b6eed051fe8e38ffb18f3b32cc0abb15dfb15373d9f254eb6c8afbd2fbc050b3c19aea9c690db4de
7
+ data.tar.gz: e29a9dd41cd963bd96e8025ee31c5c4ec5b6b2726164655707c214fa73062f4e30e72545ea2df0c1b2ce54c90816c564776f509e4b9e3a51ef672290d35d2aec
data/Changes CHANGED
@@ -1,3 +1,7 @@
1
+ 2026-06-23 v1.0.2
2
+ --------------------
3
+ * Add :raise_on_warnings option to raise a WarningError when a response contains warnings
4
+
1
5
  2026-01-24 v1.0.1
2
6
  --------------------
3
7
  * Add support for calling #paginate without a block
data/README.md CHANGED
@@ -266,6 +266,37 @@ pager.execute(query) { |page| }
266
266
 
267
267
  The `"data"` and `"pageInfo"` keys are automatically added if not provided.
268
268
 
269
+ ### Raising on Warnings
270
+
271
+ A successful GraphQL response can still contain warnings (for example an invalid search field reported under
272
+ `extensions.search`). By default these are ignored. Set `:raise_on_warnings` to `true` to raise a `WarningError`
273
+ (a subclass of `GraphQLError`) whenever the response contains warnings:
274
+
275
+ ```rb
276
+ gql = ShopifyAPI::GraphQL::Tiny.new(shop, token, :raise_on_warnings => true)
277
+
278
+ begin
279
+ gql.execute(query)
280
+ rescue ShopifyAPI::GraphQL::Tiny::WarningError => e
281
+ warn e.message # The warnings, formatted
282
+ e.response # The full GraphQL response Hash
283
+ end
284
+ ```
285
+
286
+ ## Why Use This Instead of Shopify's API Client?
287
+
288
+ - Easy-to-use
289
+ - Built-in retry
290
+ - Built-in pagination
291
+ - Lightweight
292
+
293
+ Overall, Shopify's API client is bloated trash that will give you development headaches and long-term maintenance nightmares.
294
+
295
+ We used to use it, staring way back in 2015, but eventually had to pivot away from their Ruby libraries due to developer
296
+ frustration and high maintenance cost (and don't get us started on the ShopifyApp gem!@#).
297
+
298
+ For more information see: https://github.com/Shopify/shopify-api-ruby/issues/1181
299
+
269
300
  ## Testing
270
301
 
271
302
  `cp env.template .env` and fill-in `.env` with the missing values. This requires a Shopify store.
@@ -278,6 +309,7 @@ bundle exec rake rate_limit SHOPIFY_DOMAIN=your-domain SHOPIFY_TOKEN=your-token
278
309
 
279
310
  ## See Also
280
311
 
312
+ - [`ShopifyAPI::GraphQL::Request`](https://github.com/ScreenStaring/shopify_api-graphql-request) - A higher-level wrapper around this class with improved exception handling and `:snake_case` hash key conversion
281
313
  - [Shopify Dev Tools](https://github.com/ScreenStaring/shopify-dev-tools) - Command-line program to assist with the development and/or maintenance of Shopify apps and stores
282
314
  - [Shopify ID Export](https://github.com/ScreenStaring/shopify_id_export/) - Dump Shopify product and variant IDs —along with other identifiers— to a CSV or JSON file
283
315
  - [`TinyGID`](https://github.com/sshaw/tiny_gid/) - Build Global ID (gid://) URI strings from scalar values
@@ -3,7 +3,7 @@
3
3
  module ShopifyAPI
4
4
  module GraphQL
5
5
  class Tiny
6
- VERSION = "1.0.1"
6
+ VERSION = "1.0.2"
7
7
  end
8
8
  end
9
9
  end
@@ -29,6 +29,7 @@ module ShopifyAPI
29
29
  end
30
30
 
31
31
  RateLimitError = Class.new(GraphQLError)
32
+ WarningError = Class.new(GraphQLError)
32
33
 
33
34
  class HTTPError < Error
34
35
  attr_reader :code
@@ -84,6 +85,7 @@ module ShopifyAPI
84
85
  # [:jitter (Boolean)] Exponential backoff jitter (random delay added to backoff). Defaults to +true+
85
86
  # [:multiplier (Float)] Exponential backoff multiplier. Defaults to +2.0+
86
87
  # [:debug (Boolean|IO)] Output the HTTP request/response to +STDERR+ or to its value if it's an +IO+. Defaults to +false+.
88
+ # [:raise_on_warnings (Boolean)] If +true+ raise a WarningError when the GraphQL response contains warnings. Defaults to +false+.
87
89
  #
88
90
  # === Errors
89
91
  #
@@ -96,6 +98,7 @@ module ShopifyAPI
96
98
 
97
99
  @domain = shopify_domain(shop)
98
100
  @options = options || {}
101
+ @raise_on_warnings = @options[:raise_on_warnings]
99
102
 
100
103
  @headers = DEFAULT_HEADERS.dup
101
104
  @headers[ACCESS_TOKEN_HEADER] = token
@@ -137,6 +140,8 @@ module ShopifyAPI
137
140
  # rate-limited after the configured number of retry attempts
138
141
  # * A ShopifyAPI::GraphQL::Tiny::GraphQLError is raised if the response contains an +errors+ property that is
139
142
  # not a rate-limit error
143
+ # * A ShopifyAPI::GraphQL::Tiny::WarningError is raised if the +:raise_on_warnings+ option is +true+ and the
144
+ # response contains warnings
140
145
  #
141
146
  # === Returns
142
147
  #
@@ -158,7 +163,8 @@ module ShopifyAPI
158
163
  # page.dig("data", "product", "title")
159
164
  # end
160
165
  #
161
- # The block is called for each page.
166
+ # The block is called for each page. If a block is not provided returns an instance of Enumerator::Lazy that will fetch the next
167
+ # page on each iteration.
162
168
  #
163
169
  # Using pagination requires you to include the
164
170
  # {PageInfo}[https://shopify.dev/api/admin-graphql/2022-10/objects/PageInfo]
@@ -188,9 +194,13 @@ module ShopifyAPI
188
194
  # Defaults to <code>"before"</code> or <code>"after"</code>, depending on the pagination
189
195
  # direction.
190
196
  #
197
+ # === Returns
198
+ #
199
+ # +nil+ or `Enumerator::Lazy` if no block was provided
200
+ #
191
201
  # === Errors
192
202
  #
193
- # ArgumentError
203
+ # See #execute
194
204
 
195
205
  def paginate(*options)
196
206
  Pager.new(self, options)
@@ -216,12 +226,20 @@ module ShopifyAPI
216
226
  end
217
227
 
218
228
  json = parse_json(response.body)
219
- return json unless json.include?("errors")
220
229
 
221
- return make_request(query, variables) if handle_graphql_error(json)
230
+ if json.include?("errors")
231
+ return make_request(query, variables) if handle_graphql_error(json)
232
+
233
+ message = error_message(json["errors"])
234
+ raise GraphQLError.new("failed to execute query for #@domain: #{message}", json)
235
+ end
236
+
237
+ if @raise_on_warnings
238
+ warnings = find_warnings(json)
239
+ raise WarningError.new("query for #@domain returned warnings: #{warning_message(warnings)}", json) unless warnings.empty?
240
+ end
222
241
 
223
- message = error_message(json["errors"])
224
- raise GraphQLError.new("failed to execute query for #@domain: #{message}", json)
242
+ json
225
243
  end
226
244
 
227
245
  def post(query, variables = nil)
@@ -318,6 +336,34 @@ module ShopifyAPI
318
336
  end.join(", ")
319
337
  end
320
338
 
339
+ def find_warnings(data, prop = nil)
340
+ case data
341
+ when Hash
342
+ data.flat_map do |key, value|
343
+ if key == "warnings" && value.is_a?(Array)
344
+ value.map { |w| [prop, w] }
345
+ else
346
+ find_warnings(value, key)
347
+ end
348
+ end
349
+ when Array
350
+ data.flat_map { |value| find_warnings(value, prop) }
351
+ else
352
+ []
353
+ end
354
+ end
355
+
356
+ def warning_message(warnings)
357
+ warnings.map do |prop, warning|
358
+ next warning.to_s unless warning.is_a?(Hash)
359
+
360
+ field = Array(warning["field"]).join(".")
361
+ parts = [prop]
362
+ parts << field unless field.empty?
363
+ "#{parts.join(" ")}: #{warning["message"]}"
364
+ end.join("\n")
365
+ end
366
+
321
367
  def request_attempts_remain?
322
368
  @request_attempts < @backoff_options[:max_attempts]
323
369
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shopify_api-graphql-tiny
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Skye Shaw
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2026-01-24 00:00:00.000000000 Z
10
+ date: 2026-06-23 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: net_http_timeout_errors