shopify-cli 2.15.0 → 2.15.3
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/.github/workflows/stale.yml +7 -2
- data/.vscode/settings.json +1 -2
- data/CHANGELOG.md +70 -19
- data/Gemfile +1 -0
- data/Gemfile.lock +39 -7
- data/Rakefile +48 -0
- data/ext/javy/hashes/javy-arm-macos-v0.3.0.gz.sha256 +1 -0
- data/ext/javy/hashes/javy-x86_64-linux-v0.3.0.gz.sha256 +1 -0
- data/ext/javy/hashes/javy-x86_64-macos-v0.3.0.gz.sha256 +1 -0
- data/ext/javy/hashes/javy-x86_64-windows-v0.3.0.gz.sha256 +1 -0
- data/ext/javy/version +1 -1
- data/ext/shopify-extensions/version +1 -1
- data/lib/project_types/extension/commands/check.rb +6 -1
- data/lib/project_types/extension/forms/questions/ask_template.rb +5 -8
- data/lib/project_types/extension/messages/messages.rb +11 -3
- data/lib/project_types/extension/models/development_server_requirements.rb +14 -7
- data/lib/project_types/extension/models/server_config/root.rb +2 -0
- data/lib/project_types/extension/models/specification_handlers/beacon_extension.rb +57 -0
- data/lib/project_types/extension/models/specification_handlers/beacon_extension_utils/script_config.rb +33 -0
- data/lib/project_types/extension/models/specification_handlers/beacon_extension_utils/script_config_repository.rb +75 -0
- data/lib/project_types/extension/models/specification_handlers/checkout_ui_extension.rb +16 -1
- data/lib/project_types/extension/tasks/configure_options.rb +2 -1
- data/lib/project_types/extension/tasks/convert_server_config.rb +13 -2
- data/lib/project_types/extension/tasks/merge_server_config.rb +5 -2
- data/lib/project_types/script/cli.rb +1 -0
- data/lib/project_types/script/config/extension_points.yml +18 -0
- data/lib/project_types/script/layers/application/create_script.rb +14 -6
- data/lib/project_types/script/layers/infrastructure/errors.rb +17 -0
- data/lib/project_types/script/layers/infrastructure/languages/project_creator.rb +6 -21
- data/lib/project_types/script/layers/infrastructure/script_service.rb +2 -0
- data/lib/project_types/script/layers/infrastructure/sparse_checkout_details.rb +35 -0
- data/lib/project_types/script/messages/messages.rb +3 -0
- data/lib/project_types/script/ui/error_handler.rb +11 -0
- data/lib/project_types/theme/cli.rb +1 -0
- data/lib/project_types/theme/commands/check.rb +4 -1
- data/lib/project_types/theme/commands/open.rb +2 -2
- data/lib/project_types/theme/commands/push.rb +1 -3
- data/lib/project_types/theme/commands/serve.rb +1 -0
- data/lib/project_types/theme/commands/share.rb +56 -0
- data/lib/project_types/theme/messages/messages.rb +71 -11
- data/lib/shopify_cli/changelog.rb +148 -0
- data/lib/shopify_cli/command.rb +7 -0
- data/lib/shopify_cli/command_options/command_serve_options.rb +10 -0
- data/lib/shopify_cli/commands/app/serve.rb +7 -7
- data/lib/shopify_cli/commands/login.rb +5 -2
- data/lib/shopify_cli/context.rb +13 -0
- data/lib/shopify_cli/git.rb +36 -0
- data/lib/shopify_cli/identity_auth.rb +24 -4
- data/lib/shopify_cli/messages/messages.rb +26 -5
- data/lib/shopify_cli/release.rb +194 -0
- data/lib/shopify_cli/sed.rb +19 -0
- data/lib/shopify_cli/services/app/create/rails_service.rb +10 -2
- data/lib/shopify_cli/services/app/serve/node_service.rb +2 -25
- data/lib/shopify_cli/services/app/serve/php_service.rb +2 -25
- data/lib/shopify_cli/services/app/serve/rails_service.rb +8 -28
- data/lib/shopify_cli/services/app/serve/serve_service.rb +57 -0
- data/lib/shopify_cli/services.rb +1 -0
- data/lib/shopify_cli/tasks/update_dashboard_urls.rb +7 -9
- data/lib/shopify_cli/theme/dev_server/hot-reload.js +40 -13
- data/lib/shopify_cli/theme/dev_server/hot_reload/remote_file_reloader.rb +1 -1
- data/lib/shopify_cli/theme/dev_server/hot_reload/sections_index.rb +51 -0
- data/lib/shopify_cli/theme/dev_server/hot_reload.rb +6 -1
- data/lib/shopify_cli/theme/dev_server/local_assets.rb +1 -1
- data/lib/shopify_cli/theme/dev_server/remote_watcher/json_files_update_job.rb +35 -0
- data/lib/shopify_cli/theme/dev_server/remote_watcher.rb +44 -0
- data/lib/shopify_cli/theme/dev_server/watcher.rb +2 -8
- data/lib/shopify_cli/theme/dev_server.rb +18 -5
- data/lib/shopify_cli/theme/file.rb +15 -4
- data/lib/shopify_cli/theme/syncer/checksums.rb +60 -0
- data/lib/shopify_cli/theme/syncer/forms/apply_to_all.rb +39 -0
- data/lib/shopify_cli/theme/syncer/forms/apply_to_all_form.rb +35 -0
- data/lib/shopify_cli/theme/syncer/forms/base_strategy_form.rb +62 -0
- data/lib/shopify_cli/theme/syncer/forms/select_delete_strategy.rb +27 -0
- data/lib/shopify_cli/theme/syncer/forms/select_update_strategy.rb +28 -0
- data/lib/shopify_cli/theme/syncer/ignore_helper.rb +33 -0
- data/lib/shopify_cli/theme/syncer/json_delete_handler.rb +51 -0
- data/lib/shopify_cli/theme/syncer/json_update_handler.rb +82 -0
- data/lib/shopify_cli/theme/syncer/merger.rb +53 -0
- data/lib/shopify_cli/theme/syncer/operation.rb +1 -1
- data/lib/shopify_cli/theme/syncer.rb +79 -63
- data/lib/shopify_cli/theme/theme.rb +26 -4
- data/lib/shopify_cli/theme/theme_admin_api.rb +23 -8
- data/lib/shopify_cli/thread_pool/job.rb +10 -2
- data/lib/shopify_cli/thread_pool.rb +15 -3
- data/lib/shopify_cli/tunnel.rb +9 -0
- data/lib/shopify_cli/version.rb +1 -1
- data/shopify-cli.gemspec +3 -1
- data/vendor/deps/cli-ui/lib/cli/ui/os.rb +8 -0
- metadata +30 -3
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require "thread"
|
|
3
4
|
require "json"
|
|
4
5
|
require "base64"
|
|
5
6
|
require "forwardable"
|
|
6
7
|
|
|
8
|
+
require_relative "syncer/checksums"
|
|
7
9
|
require_relative "syncer/error_reporter"
|
|
8
|
-
require_relative "syncer/
|
|
10
|
+
require_relative "syncer/ignore_helper"
|
|
11
|
+
require_relative "syncer/json_delete_handler"
|
|
12
|
+
require_relative "syncer/json_update_handler"
|
|
13
|
+
require_relative "syncer/merger"
|
|
9
14
|
require_relative "syncer/operation"
|
|
15
|
+
require_relative "syncer/standard_reporter"
|
|
10
16
|
require_relative "theme_admin_api"
|
|
11
17
|
|
|
12
18
|
module ShopifyCLI
|
|
@@ -14,36 +20,46 @@ module ShopifyCLI
|
|
|
14
20
|
class Syncer
|
|
15
21
|
extend Forwardable
|
|
16
22
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
include IgnoreHelper
|
|
24
|
+
include JsonDeleteHandler
|
|
25
|
+
include JsonUpdateHandler
|
|
26
|
+
|
|
27
|
+
QUEUEABLE_METHODS = [
|
|
28
|
+
:get, # - Updates the local file with the remote file content
|
|
29
|
+
:update, # - Updates the remote file with the local file content
|
|
30
|
+
:delete, # - Deletes the remote file
|
|
31
|
+
:union_merge, # - Union merges the local file content with the remote file content
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
attr_reader :theme, :checksums, :error_checksums
|
|
35
|
+
attr_accessor :include_filter, :ignore_filter
|
|
21
36
|
|
|
22
37
|
def_delegators :@error_reporter, :has_any_error?
|
|
23
38
|
|
|
24
|
-
def initialize(ctx, theme:, include_filter: nil, ignore_filter: nil)
|
|
39
|
+
def initialize(ctx, theme:, include_filter: nil, ignore_filter: nil, overwrite_json: true)
|
|
25
40
|
@ctx = ctx
|
|
26
41
|
@theme = theme
|
|
27
42
|
@include_filter = include_filter
|
|
28
43
|
@ignore_filter = ignore_filter
|
|
44
|
+
@overwrite_json = overwrite_json
|
|
29
45
|
@error_reporter = ErrorReporter.new(ctx)
|
|
30
46
|
@standard_reporter = StandardReporter.new(ctx)
|
|
31
47
|
@reporters = [@error_reporter, @standard_reporter]
|
|
32
48
|
|
|
33
49
|
# Queue of `Operation`s waiting to be picked up from a thread for processing.
|
|
34
50
|
@queue = Queue.new
|
|
51
|
+
|
|
35
52
|
# `Operation`s will be removed from this Array completed.
|
|
36
53
|
@pending = []
|
|
54
|
+
|
|
37
55
|
# Thread making the API requests.
|
|
38
56
|
@threads = []
|
|
57
|
+
|
|
39
58
|
# Mutex used to pause all threads when backing-off when hitting API rate limits
|
|
40
59
|
@backoff_mutex = Mutex.new
|
|
41
60
|
|
|
42
|
-
# Mutex used to coordinate changes in the checksums (shared accross all threads)
|
|
43
|
-
@checksums_mutex = Mutex.new
|
|
44
|
-
|
|
45
61
|
# Latest theme assets checksums. Updated on each upload.
|
|
46
|
-
@checksums =
|
|
62
|
+
@checksums = Checksums.new(theme)
|
|
47
63
|
|
|
48
64
|
# Checksums of assets with errors.
|
|
49
65
|
@error_checksums = []
|
|
@@ -73,6 +89,10 @@ module ShopifyCLI
|
|
|
73
89
|
files.each { |file| enqueue(:delete, file) }
|
|
74
90
|
end
|
|
75
91
|
|
|
92
|
+
def enqueue_union_merges(files)
|
|
93
|
+
files.each { |file| enqueue(:union_merge, file) }
|
|
94
|
+
end
|
|
95
|
+
|
|
76
96
|
def size
|
|
77
97
|
@pending.size
|
|
78
98
|
end
|
|
@@ -86,7 +106,11 @@ module ShopifyCLI
|
|
|
86
106
|
end
|
|
87
107
|
|
|
88
108
|
def remote_file?(file)
|
|
89
|
-
checksums.
|
|
109
|
+
checksums.has?(file)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def broken_file?(file)
|
|
113
|
+
error_checksums.include?(checksums[file.relative_path])
|
|
90
114
|
end
|
|
91
115
|
|
|
92
116
|
def wait!
|
|
@@ -135,20 +159,18 @@ module ShopifyCLI
|
|
|
135
159
|
fetch_checksums!
|
|
136
160
|
|
|
137
161
|
if delete
|
|
138
|
-
|
|
139
|
-
|
|
162
|
+
removed_json_files, removed_files = checksums
|
|
163
|
+
.keys
|
|
164
|
+
.-(@theme.theme_files.map(&:relative_path))
|
|
165
|
+
.map { |file| @theme[file] }
|
|
166
|
+
.partition(&:json?)
|
|
167
|
+
|
|
140
168
|
enqueue_deletes(removed_files)
|
|
169
|
+
enqueue_json_deletes(removed_json_files)
|
|
141
170
|
end
|
|
142
171
|
|
|
143
|
-
# Some files must be uploaded after the other ones
|
|
144
|
-
delayed_config_files = [
|
|
145
|
-
@theme["config/settings_schema.json"],
|
|
146
|
-
@theme["config/settings_data.json"],
|
|
147
|
-
]
|
|
148
|
-
|
|
149
172
|
enqueue_updates(@theme.liquid_files)
|
|
150
|
-
|
|
151
|
-
enqueue_updates(delayed_config_files)
|
|
173
|
+
enqueue_json_updates(@theme.json_files)
|
|
152
174
|
|
|
153
175
|
if delay_low_priority_files
|
|
154
176
|
# Wait for liquid & JSON files to upload, because those are rendered remotely
|
|
@@ -171,7 +193,7 @@ module ShopifyCLI
|
|
|
171
193
|
if delete
|
|
172
194
|
# Delete local files not present remotely
|
|
173
195
|
missing_files = @theme.theme_files
|
|
174
|
-
.reject { |file| checksums.
|
|
196
|
+
.reject { |file| checksums.has?(file) }.uniq
|
|
175
197
|
.reject { |file| ignore_file?(file) }
|
|
176
198
|
missing_files.each do |file|
|
|
177
199
|
@ctx.debug("rm #{file.relative_path}")
|
|
@@ -187,12 +209,13 @@ module ShopifyCLI
|
|
|
187
209
|
private
|
|
188
210
|
|
|
189
211
|
def report_error(operation, error_suffix = "")
|
|
190
|
-
@error_checksums <<
|
|
212
|
+
@error_checksums << checksums[operation.file_path]
|
|
191
213
|
@error_reporter.report("#{operation.as_error_message}#{error_suffix}")
|
|
192
214
|
end
|
|
193
215
|
|
|
194
216
|
def enqueue(method, file)
|
|
195
217
|
raise ArgumentError, "file required" unless file
|
|
218
|
+
raise ArgumentError, "method '#{method}' cannot be queued" unless QUEUEABLE_METHODS.include?(method)
|
|
196
219
|
|
|
197
220
|
operation = Operation.new(@ctx, method, @theme[file])
|
|
198
221
|
|
|
@@ -204,10 +227,10 @@ module ShopifyCLI
|
|
|
204
227
|
return
|
|
205
228
|
end
|
|
206
229
|
|
|
207
|
-
if [:update, :get].include?(method) && operation.file.exist?
|
|
230
|
+
if [:update, :get].include?(method) && operation.file.exist?
|
|
208
231
|
is_fixed = !!@error_checksums.delete(operation.file.checksum)
|
|
209
232
|
@standard_reporter.report(operation.as_fix_message) if is_fixed
|
|
210
|
-
return
|
|
233
|
+
return unless checksums.file_has_changed?(operation.file)
|
|
211
234
|
end
|
|
212
235
|
|
|
213
236
|
@pending << operation
|
|
@@ -236,7 +259,7 @@ module ShopifyCLI
|
|
|
236
259
|
end
|
|
237
260
|
|
|
238
261
|
def update(file)
|
|
239
|
-
asset = { key: file.relative_path
|
|
262
|
+
asset = { key: file.relative_path }
|
|
240
263
|
if file.text?
|
|
241
264
|
asset[:value] = file.read
|
|
242
265
|
else
|
|
@@ -253,32 +276,10 @@ module ShopifyCLI
|
|
|
253
276
|
response
|
|
254
277
|
end
|
|
255
278
|
|
|
256
|
-
def ignore_operation?(operation)
|
|
257
|
-
path = operation.file_path
|
|
258
|
-
ignore_path?(path)
|
|
259
|
-
end
|
|
260
|
-
|
|
261
|
-
def ignore_file?(file)
|
|
262
|
-
path = file.path
|
|
263
|
-
ignore_path?(path)
|
|
264
|
-
end
|
|
265
|
-
|
|
266
|
-
def ignore_path?(path)
|
|
267
|
-
ignored_by_ignore_filter?(path) || ignored_by_include_filter?(path)
|
|
268
|
-
end
|
|
269
|
-
|
|
270
|
-
def ignored_by_ignore_filter?(path)
|
|
271
|
-
ignore_filter&.ignore?(path)
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
def ignored_by_include_filter?(path)
|
|
275
|
-
!!include_filter && !include_filter.match?(path)
|
|
276
|
-
end
|
|
277
|
-
|
|
278
279
|
def get(file)
|
|
279
280
|
_status, body, response = api_client.get(
|
|
280
281
|
path: "themes/#{@theme.id}/assets.json",
|
|
281
|
-
query: URI.encode_www_form("asset[key]" => file.relative_path
|
|
282
|
+
query: URI.encode_www_form("asset[key]" => file.relative_path),
|
|
282
283
|
)
|
|
283
284
|
|
|
284
285
|
update_checksums(body)
|
|
@@ -297,37 +298,48 @@ module ShopifyCLI
|
|
|
297
298
|
_status, _body, response = api_client.delete(
|
|
298
299
|
path: "themes/#{@theme.id}/assets.json",
|
|
299
300
|
body: JSON.generate(asset: {
|
|
300
|
-
key: file.relative_path
|
|
301
|
+
key: file.relative_path,
|
|
301
302
|
})
|
|
302
303
|
)
|
|
303
304
|
|
|
304
305
|
response
|
|
305
306
|
end
|
|
306
307
|
|
|
308
|
+
def union_merge(file)
|
|
309
|
+
_status, body, response = api_client.get(
|
|
310
|
+
path: "themes/#{@theme.id}/assets.json",
|
|
311
|
+
query: URI.encode_www_form("asset[key]" => file.relative_path),
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
return response unless file.text?
|
|
315
|
+
|
|
316
|
+
remote_content = body.dig("asset", "value")
|
|
317
|
+
|
|
318
|
+
return response if remote_content.nil?
|
|
319
|
+
|
|
320
|
+
content = Merger.union_merge(file, remote_content)
|
|
321
|
+
|
|
322
|
+
file.write(content)
|
|
323
|
+
|
|
324
|
+
enqueue(:update, file)
|
|
325
|
+
|
|
326
|
+
response
|
|
327
|
+
end
|
|
328
|
+
|
|
307
329
|
def update_checksums(api_response)
|
|
308
330
|
api_response.values.flatten.each do |asset|
|
|
309
331
|
next unless asset["key"]
|
|
310
|
-
|
|
311
|
-
@checksums[asset["key"]] = asset["checksum"]
|
|
312
|
-
end
|
|
313
|
-
end
|
|
314
|
-
# Generate .liquid asset files are reported twice in checksum:
|
|
315
|
-
# once of generated, once for .liquid. We only keep the .liquid, that's the one we have
|
|
316
|
-
# on disk.
|
|
317
|
-
checksums_mutex.synchronize do
|
|
318
|
-
@checksums.reject! { |key, _| @checksums.key?("#{key}.liquid") }
|
|
332
|
+
checksums[asset["key"]] = asset["checksum"]
|
|
319
333
|
end
|
|
320
|
-
end
|
|
321
334
|
|
|
322
|
-
|
|
323
|
-
file.checksum != @checksums[file.relative_path.to_s]
|
|
335
|
+
checksums.reject_duplicated_checksums!
|
|
324
336
|
end
|
|
325
337
|
|
|
326
338
|
def parse_api_errors(exception)
|
|
327
339
|
parsed_body = JSON.parse(exception&.response&.body)
|
|
328
340
|
message = parsed_body.dig("errors", "asset") || parsed_body["message"] || exception.message
|
|
329
341
|
# Truncate to first lines
|
|
330
|
-
[message].flatten.map { |
|
|
342
|
+
[message].flatten.map { |m| m.split("\n", 2).first }
|
|
331
343
|
rescue JSON::ParserError
|
|
332
344
|
[exception.message]
|
|
333
345
|
end
|
|
@@ -339,6 +351,10 @@ module ShopifyCLI
|
|
|
339
351
|
end
|
|
340
352
|
end
|
|
341
353
|
|
|
354
|
+
def overwrite_json?
|
|
355
|
+
@overwrite_json
|
|
356
|
+
end
|
|
357
|
+
|
|
342
358
|
def backingoff?
|
|
343
359
|
@backoff_mutex.locked?
|
|
344
360
|
end
|
|
@@ -21,11 +21,11 @@ module ShopifyCLI
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def theme_files
|
|
24
|
-
glob(["**/*.liquid", "**/*.json"
|
|
24
|
+
(glob(["**/*.liquid", "**/*.json"]) + static_asset_files).uniq
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def static_asset_files
|
|
28
|
-
glob("assets/*").reject(&:liquid?)
|
|
28
|
+
glob("assets/*", raise_on_dir: true).reject(&:liquid?)
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def liquid_files
|
|
@@ -36,8 +36,11 @@ module ShopifyCLI
|
|
|
36
36
|
glob("**/*.json")
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
-
def glob(pattern)
|
|
40
|
-
root
|
|
39
|
+
def glob(pattern, raise_on_dir: false)
|
|
40
|
+
root
|
|
41
|
+
.glob(pattern)
|
|
42
|
+
.select { |path| file?(path, raise_on_dir) }
|
|
43
|
+
.map { |path| File.new(path, root) }
|
|
41
44
|
end
|
|
42
45
|
|
|
43
46
|
def theme_file?(file)
|
|
@@ -152,6 +155,13 @@ module ShopifyCLI
|
|
|
152
155
|
end
|
|
153
156
|
|
|
154
157
|
class << self
|
|
158
|
+
def create_unpublished(ctx, root: nil, name: nil)
|
|
159
|
+
name ||= random_name
|
|
160
|
+
theme = new(ctx, root: root, name: name, role: "unpublished")
|
|
161
|
+
theme.create
|
|
162
|
+
theme
|
|
163
|
+
end
|
|
164
|
+
|
|
155
165
|
def all(ctx, root: nil)
|
|
156
166
|
_status, body = fetch_themes(ctx)
|
|
157
167
|
|
|
@@ -179,6 +189,10 @@ module ShopifyCLI
|
|
|
179
189
|
|
|
180
190
|
private
|
|
181
191
|
|
|
192
|
+
def random_name
|
|
193
|
+
ShopifyCLI::Helpers::Haikunator.haikunate(9999)
|
|
194
|
+
end
|
|
195
|
+
|
|
182
196
|
def find(ctx, root, &block)
|
|
183
197
|
_status, body = fetch_themes(ctx)
|
|
184
198
|
|
|
@@ -218,6 +232,14 @@ module ShopifyCLI
|
|
|
218
232
|
|
|
219
233
|
self
|
|
220
234
|
end
|
|
235
|
+
|
|
236
|
+
def file?(path, raise_on_dir = false)
|
|
237
|
+
if raise_on_dir && ::File.directory?(path)
|
|
238
|
+
@ctx.abort(@ctx.message("theme.serve.error.invalid_subdirectory", path.to_s))
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
::File.file?(path)
|
|
242
|
+
end
|
|
221
243
|
end
|
|
222
244
|
end
|
|
223
245
|
end
|
|
@@ -41,31 +41,46 @@ module ShopifyCLI
|
|
|
41
41
|
)
|
|
42
42
|
rescue ShopifyCLI::API::APIRequestForbiddenError,
|
|
43
43
|
ShopifyCLI::API::APIRequestUnauthorizedError => error
|
|
44
|
+
|
|
45
|
+
##
|
|
44
46
|
# The Admin API returns 403 Forbidden responses on different
|
|
45
47
|
# scenarios:
|
|
46
48
|
#
|
|
47
49
|
# * when a user doesn't have permissions for a request:
|
|
48
|
-
# <APIRequestForbiddenError: 403 {}>
|
|
50
|
+
# - <APIRequestForbiddenError: 403 {}>
|
|
51
|
+
# - <APIRequestForbiddenError: 403 {"errors":"Unauthorized Access"}>
|
|
49
52
|
#
|
|
50
53
|
# * when an asset operation cannot be performed:
|
|
51
|
-
# <APIRequestForbiddenError: 403 {"message":"templates/gift_card.liquid could not be deleted"}>
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
# - <APIRequestForbiddenError: 403 {"message":"templates/gift_card.liquid could not be deleted"}>
|
|
55
|
+
#
|
|
56
|
+
if empty_response?(error) || unauthorized_response?(error)
|
|
57
|
+
return permission_error
|
|
54
58
|
end
|
|
55
59
|
|
|
56
60
|
raise error
|
|
57
61
|
end
|
|
58
62
|
|
|
59
|
-
def
|
|
63
|
+
def permission_error
|
|
60
64
|
ensure_user_error = @ctx.message("theme.ensure_user_error", shop)
|
|
61
65
|
ensure_user_try_this = @ctx.message("theme.ensure_user_try_this")
|
|
62
66
|
|
|
63
67
|
@ctx.abort(ensure_user_error, ensure_user_try_this)
|
|
64
68
|
end
|
|
65
69
|
|
|
66
|
-
def
|
|
67
|
-
|
|
68
|
-
|
|
70
|
+
def empty_response?(error)
|
|
71
|
+
response_body(error).empty?
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def unauthorized_response?(error)
|
|
75
|
+
parsed_body = JSON.parse(response_body(error))
|
|
76
|
+
errors = parsed_body["errors"].to_s
|
|
77
|
+
errors.match?(/Unauthorized Access/)
|
|
78
|
+
rescue JSON::ParserError
|
|
79
|
+
false
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def response_body(error)
|
|
83
|
+
error&.response&.body.to_s
|
|
69
84
|
end
|
|
70
85
|
end
|
|
71
86
|
end
|
|
@@ -3,10 +3,14 @@
|
|
|
3
3
|
module ShopifyCLI
|
|
4
4
|
class ThreadPool
|
|
5
5
|
class Job
|
|
6
|
-
attr_reader :error
|
|
6
|
+
attr_reader :error, :interval
|
|
7
|
+
|
|
8
|
+
def initialize(interval = 0)
|
|
9
|
+
@interval = interval
|
|
10
|
+
end
|
|
7
11
|
|
|
8
12
|
def perform!
|
|
9
|
-
raise "`#{self.class.name}#perform
|
|
13
|
+
raise "`#{self.class.name}#perform!' must be defined"
|
|
10
14
|
end
|
|
11
15
|
|
|
12
16
|
def call
|
|
@@ -22,6 +26,10 @@ module ShopifyCLI
|
|
|
22
26
|
def error?
|
|
23
27
|
!!@error
|
|
24
28
|
end
|
|
29
|
+
|
|
30
|
+
def recurring?
|
|
31
|
+
!interval.zero?
|
|
32
|
+
end
|
|
25
33
|
end
|
|
26
34
|
end
|
|
27
35
|
end
|
|
@@ -27,11 +27,23 @@ module ShopifyCLI
|
|
|
27
27
|
def spawn_thread
|
|
28
28
|
Thread.new do
|
|
29
29
|
catch(:stop_thread) do
|
|
30
|
-
loop
|
|
31
|
-
@jobs.pop.call
|
|
32
|
-
end
|
|
30
|
+
loop { perform(@jobs.pop) }
|
|
33
31
|
end
|
|
34
32
|
end
|
|
35
33
|
end
|
|
34
|
+
|
|
35
|
+
def perform(job)
|
|
36
|
+
job.call
|
|
37
|
+
reschedule(job) if job.recurring?
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def reschedule(job)
|
|
41
|
+
wait(job.interval)
|
|
42
|
+
schedule(job)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def wait(seconds)
|
|
46
|
+
sleep(seconds)
|
|
47
|
+
end
|
|
36
48
|
end
|
|
37
49
|
end
|
data/lib/shopify_cli/tunnel.rb
CHANGED
|
@@ -178,6 +178,15 @@ module ShopifyCLI
|
|
|
178
178
|
|
|
179
179
|
def fetch_url(ctx, log_path)
|
|
180
180
|
LogParser.new(log_path)
|
|
181
|
+
rescue NgrokError => e
|
|
182
|
+
# Full error messages/descriptions: https://ngrok.com/docs/errors
|
|
183
|
+
case e.message
|
|
184
|
+
when /ERR_NGROK_107/
|
|
185
|
+
ctx.abort(ctx.message("tunnel.invalid_token", e.message))
|
|
186
|
+
when /ERR_NGROK_108/
|
|
187
|
+
ctx.abort(ctx.message("tunnel.duplicate_session", e.message))
|
|
188
|
+
end
|
|
189
|
+
raise e.class, e.message
|
|
181
190
|
rescue RuntimeError => e
|
|
182
191
|
stop(ctx)
|
|
183
192
|
raise e.class, e.message
|
data/lib/shopify_cli/version.rb
CHANGED
data/shopify-cli.gemspec
CHANGED
|
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
|
|
|
28
28
|
spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
|
|
29
29
|
%x(git ls-files -z).split("\x0").reject do |f|
|
|
30
30
|
f.match(%r{^(test|spec|features|packaging)/}) ||
|
|
31
|
-
|
|
31
|
+
f.match(%r{^bin/(update-deps|shopify.bat)$})
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
34
|
spec.bindir = "bin"
|
|
@@ -49,4 +49,6 @@ Gem::Specification.new do |spec|
|
|
|
49
49
|
# Both shopify-cli and theme-check gems are owned and developed by Shopify.
|
|
50
50
|
# These gems are currently being actively developed and it's easiest to update them together.
|
|
51
51
|
spec.add_dependency("theme-check", "~> 1.10.1")
|
|
52
|
+
|
|
53
|
+
spec.extensions = ["ext/shopify-extensions/extconf.rb"]
|
|
52
54
|
end
|
|
@@ -35,6 +35,10 @@ module CLI
|
|
|
35
35
|
def shift_cursor_on_line_reset?
|
|
36
36
|
false
|
|
37
37
|
end
|
|
38
|
+
|
|
39
|
+
def path_separator
|
|
40
|
+
":"
|
|
41
|
+
end
|
|
38
42
|
end
|
|
39
43
|
end
|
|
40
44
|
|
|
@@ -58,6 +62,10 @@ module CLI
|
|
|
58
62
|
def shift_cursor_on_line_reset?
|
|
59
63
|
true
|
|
60
64
|
end
|
|
65
|
+
|
|
66
|
+
def path_separator
|
|
67
|
+
";"
|
|
68
|
+
end
|
|
61
69
|
end
|
|
62
70
|
end
|
|
63
71
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: shopify-cli
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.15.
|
|
4
|
+
version: 2.15.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Shopify
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2022-
|
|
11
|
+
date: 2022-04-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -109,7 +109,8 @@ email:
|
|
|
109
109
|
- dev-tools-education@shopify.com
|
|
110
110
|
executables:
|
|
111
111
|
- shopify
|
|
112
|
-
extensions:
|
|
112
|
+
extensions:
|
|
113
|
+
- ext/shopify-extensions/extconf.rb
|
|
113
114
|
extra_rdoc_files: []
|
|
114
115
|
files:
|
|
115
116
|
- ".devcontainer.json"
|
|
@@ -157,15 +158,19 @@ files:
|
|
|
157
158
|
- ext/javy/hashes/javy-arm-macos-v0.1.0.gz.sha256
|
|
158
159
|
- ext/javy/hashes/javy-arm-macos-v0.2.0.gz.sha256
|
|
159
160
|
- ext/javy/hashes/javy-arm-macos-v0.2.1.gz.sha256
|
|
161
|
+
- ext/javy/hashes/javy-arm-macos-v0.3.0.gz.sha256
|
|
160
162
|
- ext/javy/hashes/javy-x86_64-linux-v0.1.0.gz.sha256
|
|
161
163
|
- ext/javy/hashes/javy-x86_64-linux-v0.2.0.gz.sha256
|
|
162
164
|
- ext/javy/hashes/javy-x86_64-linux-v0.2.1.gz.sha256
|
|
165
|
+
- ext/javy/hashes/javy-x86_64-linux-v0.3.0.gz.sha256
|
|
163
166
|
- ext/javy/hashes/javy-x86_64-macos-v0.1.0.gz.sha256
|
|
164
167
|
- ext/javy/hashes/javy-x86_64-macos-v0.2.0.gz.sha256
|
|
165
168
|
- ext/javy/hashes/javy-x86_64-macos-v0.2.1.gz.sha256
|
|
169
|
+
- ext/javy/hashes/javy-x86_64-macos-v0.3.0.gz.sha256
|
|
166
170
|
- ext/javy/hashes/javy-x86_64-windows-v0.1.0.gz.sha256
|
|
167
171
|
- ext/javy/hashes/javy-x86_64-windows-v0.2.0.gz.sha256
|
|
168
172
|
- ext/javy/hashes/javy-x86_64-windows-v0.2.1.gz.sha256
|
|
173
|
+
- ext/javy/hashes/javy-x86_64-windows-v0.3.0.gz.sha256
|
|
169
174
|
- ext/javy/javy.rb
|
|
170
175
|
- ext/javy/version
|
|
171
176
|
- ext/shopify-extensions/extconf.rb
|
|
@@ -246,6 +251,9 @@ files:
|
|
|
246
251
|
- lib/project_types/extension/models/server_config/root.rb
|
|
247
252
|
- lib/project_types/extension/models/server_config/user.rb
|
|
248
253
|
- lib/project_types/extension/models/specification.rb
|
|
254
|
+
- lib/project_types/extension/models/specification_handlers/beacon_extension.rb
|
|
255
|
+
- lib/project_types/extension/models/specification_handlers/beacon_extension_utils/script_config.rb
|
|
256
|
+
- lib/project_types/extension/models/specification_handlers/beacon_extension_utils/script_config_repository.rb
|
|
249
257
|
- lib/project_types/extension/models/specification_handlers/checkout_post_purchase.rb
|
|
250
258
|
- lib/project_types/extension/models/specification_handlers/checkout_ui_extension.rb
|
|
251
259
|
- lib/project_types/extension/models/specification_handlers/default.rb
|
|
@@ -334,6 +342,7 @@ files:
|
|
|
334
342
|
- lib/project_types/script/layers/infrastructure/script_service.rb
|
|
335
343
|
- lib/project_types/script/layers/infrastructure/script_uploader.rb
|
|
336
344
|
- lib/project_types/script/layers/infrastructure/service_locator.rb
|
|
345
|
+
- lib/project_types/script/layers/infrastructure/sparse_checkout_details.rb
|
|
337
346
|
- lib/project_types/script/loaders/project.rb
|
|
338
347
|
- lib/project_types/script/loaders/specification_handler.rb
|
|
339
348
|
- lib/project_types/script/messages/messages.rb
|
|
@@ -353,6 +362,7 @@ files:
|
|
|
353
362
|
- lib/project_types/theme/commands/pull.rb
|
|
354
363
|
- lib/project_types/theme/commands/push.rb
|
|
355
364
|
- lib/project_types/theme/commands/serve.rb
|
|
365
|
+
- lib/project_types/theme/commands/share.rb
|
|
356
366
|
- lib/project_types/theme/conversions/base_glob.rb
|
|
357
367
|
- lib/project_types/theme/conversions/ignore_glob.rb
|
|
358
368
|
- lib/project_types/theme/conversions/include_glob.rb
|
|
@@ -369,6 +379,7 @@ files:
|
|
|
369
379
|
- lib/shopify_cli/admin_api/schema.rb
|
|
370
380
|
- lib/shopify_cli/api.rb
|
|
371
381
|
- lib/shopify_cli/app_type_detector.rb
|
|
382
|
+
- lib/shopify_cli/changelog.rb
|
|
372
383
|
- lib/shopify_cli/command.rb
|
|
373
384
|
- lib/shopify_cli/command/app_sub_command.rb
|
|
374
385
|
- lib/shopify_cli/command/project_command.rb
|
|
@@ -444,11 +455,13 @@ files:
|
|
|
444
455
|
- lib/shopify_cli/project.rb
|
|
445
456
|
- lib/shopify_cli/project_commands.rb
|
|
446
457
|
- lib/shopify_cli/project_type.rb
|
|
458
|
+
- lib/shopify_cli/release.rb
|
|
447
459
|
- lib/shopify_cli/reporting_configuration_controller.rb
|
|
448
460
|
- lib/shopify_cli/resolve_constant.rb
|
|
449
461
|
- lib/shopify_cli/resources.rb
|
|
450
462
|
- lib/shopify_cli/resources/env_file.rb
|
|
451
463
|
- lib/shopify_cli/result.rb
|
|
464
|
+
- lib/shopify_cli/sed.rb
|
|
452
465
|
- lib/shopify_cli/services.rb
|
|
453
466
|
- lib/shopify_cli/services/app/connect_service.rb
|
|
454
467
|
- lib/shopify_cli/services/app/create/node_service.rb
|
|
@@ -461,6 +474,7 @@ files:
|
|
|
461
474
|
- lib/shopify_cli/services/app/serve/node_service.rb
|
|
462
475
|
- lib/shopify_cli/services/app/serve/php_service.rb
|
|
463
476
|
- lib/shopify_cli/services/app/serve/rails_service.rb
|
|
477
|
+
- lib/shopify_cli/services/app/serve/serve_service.rb
|
|
464
478
|
- lib/shopify_cli/services/app/tunnel/auth_service.rb
|
|
465
479
|
- lib/shopify_cli/services/app/tunnel/start_service.rb
|
|
466
480
|
- lib/shopify_cli/services/app/tunnel/stop_service.rb
|
|
@@ -486,10 +500,13 @@ files:
|
|
|
486
500
|
- lib/shopify_cli/theme/dev_server/hot-reload.js
|
|
487
501
|
- lib/shopify_cli/theme/dev_server/hot_reload.rb
|
|
488
502
|
- lib/shopify_cli/theme/dev_server/hot_reload/remote_file_reloader.rb
|
|
503
|
+
- lib/shopify_cli/theme/dev_server/hot_reload/sections_index.rb
|
|
489
504
|
- lib/shopify_cli/theme/dev_server/local_assets.rb
|
|
490
505
|
- lib/shopify_cli/theme/dev_server/proxy.rb
|
|
491
506
|
- lib/shopify_cli/theme/dev_server/proxy/template_param_builder.rb
|
|
492
507
|
- lib/shopify_cli/theme/dev_server/reload_mode.rb
|
|
508
|
+
- lib/shopify_cli/theme/dev_server/remote_watcher.rb
|
|
509
|
+
- lib/shopify_cli/theme/dev_server/remote_watcher/json_files_update_job.rb
|
|
493
510
|
- lib/shopify_cli/theme/dev_server/sse.rb
|
|
494
511
|
- lib/shopify_cli/theme/dev_server/watcher.rb
|
|
495
512
|
- lib/shopify_cli/theme/dev_server/web_server.rb
|
|
@@ -500,7 +517,17 @@ files:
|
|
|
500
517
|
- lib/shopify_cli/theme/include_filter.rb
|
|
501
518
|
- lib/shopify_cli/theme/mime_type.rb
|
|
502
519
|
- lib/shopify_cli/theme/syncer.rb
|
|
520
|
+
- lib/shopify_cli/theme/syncer/checksums.rb
|
|
503
521
|
- lib/shopify_cli/theme/syncer/error_reporter.rb
|
|
522
|
+
- lib/shopify_cli/theme/syncer/forms/apply_to_all.rb
|
|
523
|
+
- lib/shopify_cli/theme/syncer/forms/apply_to_all_form.rb
|
|
524
|
+
- lib/shopify_cli/theme/syncer/forms/base_strategy_form.rb
|
|
525
|
+
- lib/shopify_cli/theme/syncer/forms/select_delete_strategy.rb
|
|
526
|
+
- lib/shopify_cli/theme/syncer/forms/select_update_strategy.rb
|
|
527
|
+
- lib/shopify_cli/theme/syncer/ignore_helper.rb
|
|
528
|
+
- lib/shopify_cli/theme/syncer/json_delete_handler.rb
|
|
529
|
+
- lib/shopify_cli/theme/syncer/json_update_handler.rb
|
|
530
|
+
- lib/shopify_cli/theme/syncer/merger.rb
|
|
504
531
|
- lib/shopify_cli/theme/syncer/operation.rb
|
|
505
532
|
- lib/shopify_cli/theme/syncer/standard_reporter.rb
|
|
506
533
|
- lib/shopify_cli/theme/theme.rb
|