lucid-shopify 0.60.0 → 0.63.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a2000b0881f8f32a1ae28c1e81f75c4e10c99fb386e090087c930835453a7c20
4
- data.tar.gz: 871ddf85d10f96e5f03c253436d4fb49f76da54ed0e1bca68428fa2ae4cd095e
3
+ metadata.gz: ffe59e48e1d046fa4eb07460911384691bda6c07981b056cb3c89dd48d95514f
4
+ data.tar.gz: 778d7a488544cb0452290010eff0ff59db765afd55abd8bbdefd674b38984a79
5
5
  SHA512:
6
- metadata.gz: 17cbb58d6af88ebe841ff7ad8d2217512a7a11c78f40763a9061ef85e4e132d0334cce964235eed844d7d231a2657107ac3a493a091b6b2aba360d8f4042f925
7
- data.tar.gz: bfebbb6f59bb8592827a6b3264c00bef9d3839e9236628d4e8eb91da30af9cc032e15500d389f366d4c8c7b967b8bbe75612d28d3de8658e3124fc13d1495661
6
+ metadata.gz: 9ed2477757ec40d6464699bc8a930604f21b5aee5ccabaef0eebd1113fa4a73a1edbb76db8bfc50cb35a53f11440fda704535e0e982daa490f9e6e03deab66d8
7
+ data.tar.gz: 03d6ea262fc118da219fb18f11478da1d4a384c0d50b7a67e6b4941abd6112d82c854a4dd57f5de7b5510d28b781d0e647f28cd8ed1f14dffa6cca71753dc126
data/README.md CHANGED
@@ -35,7 +35,7 @@ Setup
35
35
 
36
36
  Lucid::Shopify.configure do |config|
37
37
  config.api_key = '...'
38
- config.api_version = '...' # e.g. '2020-01'
38
+ config.api_version = '...' # e.g. '2020-04'
39
39
  config.billing_callback_uri = '...'
40
40
  config.callback_uri = '...' # (for OAuth; unused by this gem)
41
41
  config.logger = Logger.new(STDOUT)
@@ -45,7 +45,7 @@ module Lucid
45
45
  extend Dry::Configurable
46
46
 
47
47
  setting :api_key
48
- setting :api_version, '2020-01'
48
+ setting :api_version, '2020-04'
49
49
  setting :billing_callback_uri
50
50
  setting :callback_uri
51
51
  setting :logger, Logger.new(File::NULL).freeze
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'json'
4
4
  require 'lucid/shopify'
5
+ require 'timeout'
5
6
 
6
7
  module Lucid
7
8
  module Shopify
@@ -13,6 +14,8 @@ module Lucid
13
14
  FailedOperationError = Class.new(OperationError)
14
15
  ObsoleteOperationError = Class.new(OperationError)
15
16
 
17
+ TimeoutError = Class.new(Error)
18
+
16
19
  class Operation
17
20
  include Dry::Initializer.define -> do
18
21
  # @return [Client]
@@ -31,6 +34,11 @@ module Lucid
31
34
  # @param http [HTTP::Client]
32
35
  #
33
36
  # @yield [Enumerator<Hash>] yields each parsed line of JSONL
37
+ #
38
+ # @raise CanceledOperationError
39
+ # @raise ExpiredOperationError
40
+ # @raise FailedOperationError
41
+ # @raise ObsoleteOperationError
34
42
  def call(delay: 1, http: Container[:http], &block)
35
43
  url = loop do
36
44
  status, url = poll
@@ -70,23 +78,52 @@ module Lucid
70
78
  end
71
79
 
72
80
  # Cancel the bulk operation.
81
+ #
82
+ # @raise ObsoleteOperationError
83
+ # @raise TimeoutError
73
84
  def cancel
74
- client.post_graphql(credentials, <<~QUERY)
75
- mutation {
76
- bulkOperationCancel(id: "#{id}") {
77
- userErrors {
78
- field
79
- message
85
+ begin
86
+ client.post_graphql(credentials, <<~QUERY)
87
+ mutation {
88
+ bulkOperationCancel(id: "#{id}") {
89
+ userErrors {
90
+ field
91
+ message
92
+ }
80
93
  }
81
94
  }
82
- }
83
- QUERY
95
+ QUERY
96
+ rescue Response::GraphQLClientError => e
97
+ return if e.response.error_message?([
98
+ /cannot be canceled when it is completed/,
99
+ ])
100
+
101
+ raise e
102
+ end
84
103
 
85
- loop do
86
- status, _ = poll
104
+ poll_until(['CANCELED', 'COMPLETED'])
105
+ end
87
106
 
88
- break unless status == 'CANCELING'
107
+ # Poll until operation status is met.
108
+ #
109
+ # @param statuses [Array<String>] to terminate polling on
110
+ # @param timeout [Integer] in seconds
111
+ #
112
+ # @raise ObsoleteOperationError
113
+ # @raise TimeoutError
114
+ def poll_until(statuses, timeout: 60)
115
+ Timeout.timeout(timeout) do
116
+ loop do
117
+ status, _ = poll
118
+
119
+ break if statuses.any? { |expected_status| status == expected_status }
120
+ end
89
121
  end
122
+ rescue Timeout::Error
123
+ raise TimeoutError, 'exceeded %s seconds polling for status %s' % [
124
+ timeout,
125
+ statuses.join(', '),
126
+ ]
90
127
  end
91
128
 
92
129
  # @return [Array(String, String | nil)] the operation status and the
@@ -111,7 +148,8 @@ module Lucid
111
148
  end
112
149
  end
113
150
 
114
- # Create and start a new bulk operation via the GraphQL API.
151
+ # Create and start a new bulk operation via the GraphQL API. Any currently
152
+ # running bulk operations are cancelled.
115
153
  #
116
154
  # @param client [Client]
117
155
  # @param credentials [Credentials]
@@ -154,7 +192,12 @@ module Lucid
154
192
  }
155
193
  QUERY
156
194
 
157
- Operation.new(client, credentials, op['id']).cancel if op && op['status'] == 'RUNNING'
195
+ case op&.fetch('status')
196
+ when 'CANCELING'
197
+ Operation.new(client, credentials, op['id']).poll_until(['CANCELED'])
198
+ when 'CREATED', 'RUNNING'
199
+ Operation.new(client, credentials, op['id']).cancel
200
+ end
158
201
 
159
202
  id = client.post_graphql(credentials, <<~QUERY)['data']['bulkOperationRunQuery']['bulkOperation']['id']
160
203
  mutation {
@@ -111,11 +111,18 @@ module Lucid
111
111
  # @raise [ClientError] for status 4xx
112
112
  # @raise [ServerError] for status 5xx
113
113
  #
114
- # @note https://help.shopify.com/en/api/getting-started/response-status-codes
114
+ # @note https://shopify.dev/concepts/about-apis/response-codes
115
115
  def assert!
116
116
  case status_code
117
117
  when 402
118
118
  raise ShopError.new(request, self), 'Shop is frozen, awaiting payment'
119
+ when 403
120
+ # NOTE: Not sure what this one means (undocumented).
121
+ if error_message?([/unavailable shop/i])
122
+ raise ShopError.new(request, self), 'Shop is unavailable'
123
+ else
124
+ raise ClientError.new(request, self)
125
+ end
119
126
  when 423
120
127
  raise ShopError.new(request, self), 'Shop is locked'
121
128
  when 400..499
@@ -207,7 +214,7 @@ module Lucid
207
214
  # @return [Array<String>]
208
215
  def error_messages
209
216
  errors.map do |field, message|
210
- "#{field} #{message}"
217
+ "#{message} [#{field}]"
211
218
  end
212
219
  end
213
220
 
@@ -222,12 +229,14 @@ module Lucid
222
229
  #
223
230
  # @return [Boolean]
224
231
  def error_message?(messages)
232
+ all_messages = error_messages + user_error_messages
233
+
225
234
  messages.any? do |message|
226
235
  case message
227
236
  when Regexp
228
- error_messages.any? { |other_message| other_message.match?(message) }
237
+ all_messages.any? { |other_message| other_message.match?(message) }
229
238
  when String
230
- error_messages.include?(message)
239
+ all_messages.include?(message)
231
240
  end
232
241
  end
233
242
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Lucid
4
4
  module Shopify
5
- VERSION = '0.60.0'
5
+ VERSION = '0.63.1'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lucid-shopify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.60.0
4
+ version: 0.63.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kelsey Judson
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-16 00:00:00.000000000 Z
11
+ date: 2020-06-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dotenv
@@ -136,7 +136,7 @@ dependencies:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
138
  version: '4.1'
139
- description:
139
+ description:
140
140
  email: kelsey@lucid.nz
141
141
  executables: []
142
142
  extensions: []
@@ -179,7 +179,7 @@ homepage: https://github.com/lucidnz/gem-lucid-shopify
179
179
  licenses:
180
180
  - ISC
181
181
  metadata: {}
182
- post_install_message:
182
+ post_install_message:
183
183
  rdoc_options: []
184
184
  require_paths:
185
185
  - lib
@@ -195,7 +195,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
195
195
  version: '0'
196
196
  requirements: []
197
197
  rubygems_version: 3.1.2
198
- signing_key:
198
+ signing_key:
199
199
  specification_version: 4
200
200
  summary: Shopify client library
201
201
  test_files: []