lucid-shopify 0.61.0 → 0.64.0

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: ffa0adb3d84baa78fe2fdbde5edfa2b7197a0a0edc9787eae34c3421b593a89f
4
- data.tar.gz: e06b3011191e2a29568ea4472a585142e4efea6907b9a61c40767bcba08f2cda
3
+ metadata.gz: 1b0b5d01a7f0169127f5cb34c55771e87790f9e15059e384874321566cb257c4
4
+ data.tar.gz: fac44b65de85d005f9affe1532892a2b3baaa85b066ca407ffcadfe880c3d785
5
5
  SHA512:
6
- metadata.gz: ff81335689e3fd841c1971eda673028ecfb3d050cd37239459618e9ff3e1f69899496a638ccc371596d2fecaced6df24468727b3a36f005487219522a2acc0ed
7
- data.tar.gz: 877b4689633a3c0535fbee9d412eace6c0d888f85117e998e68b4288ae19c59d59168bef43588ba94e3359abdf7316c01ab4c3669aa63194dc8c69470a6b7ebd
6
+ metadata.gz: 1087a99b8ad46cb6fe571a4812dfc47eb3c67cfba2dd85d4d0c9bc069913f0ff9c8e869ed8b2e9a0a172307751a156eef080e0d560d573076946a32345f90fc8
7
+ data.tar.gz: 929282d2d2b752515a143cd06fcb26b66b1209594be0785c1cd9cc2418476f55c7ee63f7f95d975ca8530f276e2592269ee822f5dba5c99f56ed032fcffafdcb
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
@@ -155,7 +192,12 @@ module Lucid
155
192
  }
156
193
  QUERY
157
194
 
158
- 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
159
201
 
160
202
  id = client.post_graphql(credentials, <<~QUERY)['data']['bulkOperationRunQuery']['bulkOperation']['id']
161
203
  mutation {
@@ -15,7 +15,7 @@ module Lucid
15
15
  case link_header
16
16
  # NOTE: There is a strange behaviour where it seems that if the header
17
17
  # value exceeds a certain length, it is split into chunks. It seems that
18
- # if you use {HTTP::Headers#get}, you will always get {Array<String},
18
+ # if you use {HTTP::Headers#get}, you will always get {Array<String>},
19
19
  # and it is the special behaviour of {HTTP::Headers#[]} causing this.
20
20
  #
21
21
  # However, why is it split in the first place? Does Shopify send
@@ -29,8 +29,8 @@ module Lucid
29
29
  ClientError = Class.new(Error)
30
30
  ServerError = Class.new(Error)
31
31
  ShopError = Class.new(Error)
32
-
33
- class GraphQLClientError < ClientError
32
+ AccessTokenError = Class.new(ClientError)
33
+ GraphQLClientError = Class.new(ClientError) do
34
34
  def message
35
35
  case
36
36
  when response.errors?
@@ -111,11 +111,24 @@ 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
+ when 401
118
+ if error_message?([/access token/i])
119
+ raise AccessTokenError.new(request, self), 'Invalid access token'
120
+ else
121
+ raise ClientError.new(request, self)
122
+ end
117
123
  when 402
118
124
  raise ShopError.new(request, self), 'Shop is frozen, awaiting payment'
125
+ when 403
126
+ # NOTE: Not sure what this one means (undocumented).
127
+ if error_message?([/unavailable shop/i])
128
+ raise ShopError.new(request, self), 'Shop is unavailable'
129
+ else
130
+ raise ClientError.new(request, self)
131
+ end
119
132
  when 423
120
133
  raise ShopError.new(request, self), 'Shop is locked'
121
134
  when 400..499
@@ -222,12 +235,14 @@ module Lucid
222
235
  #
223
236
  # @return [Boolean]
224
237
  def error_message?(messages)
238
+ all_messages = error_messages + user_error_messages
239
+
225
240
  messages.any? do |message|
226
241
  case message
227
242
  when Regexp
228
- error_messages.any? { |other_message| other_message.match?(message) }
243
+ all_messages.any? { |other_message| other_message.match?(message) }
229
244
  when String
230
- error_messages.include?(message)
245
+ all_messages.include?(message)
231
246
  end
232
247
  end
233
248
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Lucid
4
4
  module Shopify
5
- VERSION = '0.61.0'
5
+ VERSION = '0.64.0'
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.61.0
4
+ version: 0.64.0
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-08-15 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: []