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 +4 -4
- data/Changes +4 -0
- data/README.md +32 -0
- data/lib/shopify_api/graphql/tiny/version.rb +1 -1
- data/lib/shopify_api/graphql/tiny.rb +52 -6
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 18495ff517670050b05536c1ef5fda702e689a4ffab229eba78fd2aba055dce5
|
|
4
|
+
data.tar.gz: c374cf2ae48b8ed7de70b5ec8501841593535ad21ef2d5591deb17c7dc96fdef
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3388c846e2190e5996f780bf847d28f66c9336e0a96d53a8b6eed051fe8e38ffb18f3b32cc0abb15dfb15373d9f254eb6c8afbd2fbc050b3c19aea9c690db4de
|
|
7
|
+
data.tar.gz: e29a9dd41cd963bd96e8025ee31c5c4ec5b6b2726164655707c214fa73062f4e30e72545ea2df0c1b2ce54c90816c564776f509e4b9e3a51ef672290d35d2aec
|
data/Changes
CHANGED
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
|
|
@@ -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
|
-
#
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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-
|
|
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
|