shopify-cli 2.20.1 → 2.23.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/CODEOWNERS +1 -1
- data/.github/workflows/shopify.yml +0 -1
- data/CHANGELOG.md +26 -0
- data/Gemfile.lock +1 -1
- data/lib/project_types/script/config/extension_points.yml +0 -15
- data/lib/project_types/theme/commands/pull.rb +5 -1
- data/lib/project_types/theme/commands/push.rb +18 -9
- data/lib/project_types/theme/messages/messages.rb +22 -9
- data/lib/shopify_cli/constants.rb +2 -0
- data/lib/shopify_cli/context.rb +3 -2
- data/lib/shopify_cli/core/cli_version.rb +20 -0
- data/lib/shopify_cli/core/entry_point.rb +21 -7
- data/lib/shopify_cli/core.rb +1 -0
- data/lib/shopify_cli/environment.rb +11 -0
- data/lib/shopify_cli/messages/messages.rb +10 -0
- data/lib/shopify_cli/project.rb +1 -10
- data/lib/shopify_cli/resources/env_file.rb +1 -1
- data/lib/shopify_cli/theme/dev_server/hot-reload.js +22 -7
- data/lib/shopify_cli/theme/dev_server/hot_reload/remote_file_deleter.rb +62 -0
- data/lib/shopify_cli/theme/dev_server/hot_reload.rb +24 -2
- data/lib/shopify_cli/theme/dev_server/proxy.rb +1 -0
- data/lib/shopify_cli/theme/syncer/ignore_helper.rb +1 -1
- data/lib/shopify_cli/theme/syncer.rb +8 -2
- data/lib/shopify_cli/theme/theme.rb +5 -0
- data/lib/shopify_cli/utilities.rb +9 -0
- data/lib/shopify_cli/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db890ff22a5395154b92a4cf782ad621c2462b8aac8cc843c102be2a388a098b
|
4
|
+
data.tar.gz: e1ce745c465a52a84b33075e0b7ba8ffe15a10397061a9a5bea5bc1bd3669618
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 506f249416682dda65299eaf0dd6d589f1dea1fbb2097f92f4738e5ad529184aabeb3b84387ed8d012db60da271e28ef53df24a9c49a85bdcfab0d722be23459
|
7
|
+
data.tar.gz: 7fdb0b575be5f09c9185479a04313bb16f0144e21316ebe48e17e98ef80d9766d765760c6d65fdcca1611eb367f2a3b59153c60f6406f92e5c98fa4cd1c36b58
|
data/.github/CODEOWNERS
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,32 @@ From version 2.6.0, the sections in this file adhere to the [keep a changelog](h
|
|
2
2
|
|
3
3
|
## [Unreleased]
|
4
4
|
|
5
|
+
## Version 2.23.0 - 2022-08-22
|
6
|
+
|
7
|
+
### Fixed
|
8
|
+
* [#2528](https://github.com/Shopify/shopify-cli/pull/2528): Switch from using absolute file paths to relative paths for ignore filter
|
9
|
+
|
10
|
+
### Added
|
11
|
+
* [#2520](https://github.com/Shopify/shopify-cli/pull/2520): Add the option to ignore new version warnings by passing the `SHOPIFY_CLI_RUN_AS_SUBPROCESS` environment variable
|
12
|
+
* [#2440](https://github.com/Shopify/shopify-cli/pull/2440): Warn when using CLI 2.0 in a CLI 3.0 project
|
13
|
+
|
14
|
+
## Version 2.22.0 - 2022-08-08
|
15
|
+
|
16
|
+
### Fixed
|
17
|
+
* [#2512](https://github.com/Shopify/shopify-cli/pull/2512): Add the `-t/--theme` parameter to the `shopify theme serve -h` message
|
18
|
+
* [#2505](https://github.com/Shopify/shopify-cli/pull/2505): Show warning messages when `shopify theme push/pull` has errors
|
19
|
+
|
20
|
+
## Version 2.21.0 - 2022-08-03
|
21
|
+
|
22
|
+
### Fixed
|
23
|
+
* [#2453](https://github.com/Shopify/shopify-cli/pull/2453): Fix [#2382](https://github.com/Shopify/shopify-cli/issues/2382): Ensure we wait 24 hours to show update message again
|
24
|
+
* [#2463](https://github.com/Shopify/shopify-cli/pull/2463): Fix for "Keep the remote version" deletes files on new development theme
|
25
|
+
* [#2405](https://github.com/Shopify/shopify-cli/pull/2405): Fix `theme serve` to trigger page refresh when a file is deleted
|
26
|
+
* [#2489](https://github.com/Shopify/shopify-cli/pull/2489): Fix `theme serve` to hot reload many occurrences of a stylesheet
|
27
|
+
|
28
|
+
### Added
|
29
|
+
* [#2496](https://github.com/Shopify/shopify-cli/pull/2496): Accept storefront renderer token from ENV variable
|
30
|
+
|
5
31
|
## Version 2.20.1 - 2022-07-18
|
6
32
|
|
7
33
|
### Fixed
|
data/Gemfile.lock
CHANGED
@@ -1,14 +1,3 @@
|
|
1
|
-
payment_methods:
|
2
|
-
domain: 'checkout'
|
3
|
-
libraries:
|
4
|
-
typescript:
|
5
|
-
beta: true
|
6
|
-
package: "@shopify/scripts-checkout-apis"
|
7
|
-
repo: "https://github.com/Shopify/function-examples"
|
8
|
-
wasm:
|
9
|
-
repo: "https://github.com/Shopify/function-examples"
|
10
|
-
rust:
|
11
|
-
repo: "https://github.com/Shopify/function-examples"
|
12
1
|
payment_customization:
|
13
2
|
beta: true
|
14
3
|
domain: 'checkout'
|
@@ -20,10 +9,6 @@ payment_customization:
|
|
20
9
|
shipping_methods:
|
21
10
|
domain: 'checkout'
|
22
11
|
libraries:
|
23
|
-
typescript:
|
24
|
-
beta: true
|
25
|
-
package: "@shopify/scripts-checkout-apis"
|
26
|
-
repo: "https://github.com/Shopify/function-examples"
|
27
12
|
wasm:
|
28
13
|
repo: "https://github.com/Shopify/function-examples"
|
29
14
|
rust:
|
@@ -52,7 +52,11 @@ module Theme
|
|
52
52
|
CLI::UI::Frame.open(@ctx.message("theme.pull.pulling", theme.name, theme.id, theme.shop)) do
|
53
53
|
UI::SyncProgressBar.new(syncer).progress(:download_theme!, delete: delete)
|
54
54
|
end
|
55
|
-
|
55
|
+
if syncer.has_any_error?
|
56
|
+
@ctx.warn(@ctx.message("theme.pull.done_with_errors"))
|
57
|
+
else
|
58
|
+
@ctx.done(@ctx.message("theme.pull.done"))
|
59
|
+
end
|
56
60
|
rescue ShopifyCLI::API::APIRequestNotFoundError
|
57
61
|
@ctx.abort(@ctx.message("theme.pull.theme_not_found", "##{theme.id}"))
|
58
62
|
ensure
|
@@ -63,20 +63,12 @@ module Theme
|
|
63
63
|
syncer.start_threads
|
64
64
|
if options.flags[:json]
|
65
65
|
syncer.upload_theme!(delete: delete)
|
66
|
-
puts(JSON.generate(theme: theme.to_h))
|
67
66
|
else
|
68
67
|
CLI::UI::Frame.open(@ctx.message("theme.push.info.pushing", theme.name, theme.id, theme.shop)) do
|
69
68
|
UI::SyncProgressBar.new(syncer).progress(:upload_theme!, delete: delete)
|
70
69
|
end
|
71
|
-
|
72
|
-
if options.flags[:publish]
|
73
|
-
theme.publish
|
74
|
-
@ctx.done(@ctx.message("theme.publish.done", theme.preview_url))
|
75
|
-
else
|
76
|
-
@ctx.done(@ctx.message("theme.push.done", theme.preview_url, theme.editor_url))
|
77
|
-
end
|
78
70
|
end
|
79
|
-
|
71
|
+
push_completion_handler(theme, syncer.has_any_error?)
|
80
72
|
ensure
|
81
73
|
syncer.shutdown
|
82
74
|
end
|
@@ -90,6 +82,23 @@ module Theme
|
|
90
82
|
|
91
83
|
private
|
92
84
|
|
85
|
+
def push_completion_handler(theme, has_errors)
|
86
|
+
if options.flags[:json]
|
87
|
+
output = { theme: theme.to_h }
|
88
|
+
output[:warning] = @ctx.message("theme.push.with_errors") if has_errors
|
89
|
+
|
90
|
+
puts(JSON.generate(output))
|
91
|
+
elsif options.flags[:publish]
|
92
|
+
theme.publish
|
93
|
+
return @ctx.done(@ctx.message("theme.publish.done", theme.preview_url)) unless has_errors
|
94
|
+
@ctx.warn(@ctx.message("theme.publish.done_with_errors", theme.preview_url))
|
95
|
+
else
|
96
|
+
return @ctx.done(@ctx.message("theme.push.done", theme.preview_url, theme.editor_url)) unless has_errors
|
97
|
+
@ctx.warn(@ctx.message("theme.push.done_with_errors", theme.preview_url, theme.editor_url))
|
98
|
+
end
|
99
|
+
raise ShopifyCLI::AbortSilent if has_errors
|
100
|
+
end
|
101
|
+
|
93
102
|
def find_theme(root, theme_id: nil, theme: nil, live: nil, development: nil, unpublished: nil, **_args)
|
94
103
|
if theme_id
|
95
104
|
@ctx.warn(@ctx.message("theme.push.deprecated_themeid"))
|
@@ -43,6 +43,7 @@ module Theme
|
|
43
43
|
Run without arguments to select theme from a list.
|
44
44
|
HELP
|
45
45
|
done: "Your theme is now live at %s",
|
46
|
+
done_with_errors: "{{warning:Your theme was published with errors and is now live at %s.}}",
|
46
47
|
not_found: "Theme #%s does not exist",
|
47
48
|
no_themes_error: "You don't have any theme to be published.",
|
48
49
|
no_themes_resolution: "Try to create an unpublished theme with {{command:theme push -u -t <theme_name>}}.",
|
@@ -102,7 +103,17 @@ module Theme
|
|
102
103
|
{{info:Customize this theme in the Theme Editor:}}
|
103
104
|
{{underline:%s}}
|
104
105
|
DONE
|
106
|
+
done_with_errors: <<~WARN,
|
107
|
+
{{yellow:Your theme was pushed with errors.}}
|
108
|
+
|
109
|
+
{{info:View your theme:}}
|
110
|
+
{{underline:%s}}
|
111
|
+
|
112
|
+
{{info:Customize this theme in the Theme Editor:}}
|
113
|
+
{{underline:%s}}
|
114
|
+
WARN
|
105
115
|
name: "Theme name",
|
116
|
+
with_errors: "Theme pushed with errors.",
|
106
117
|
},
|
107
118
|
serve: {
|
108
119
|
theme_not_found: "Theme \"%s\" doesn't exist",
|
@@ -112,14 +123,15 @@ module Theme
|
|
112
123
|
Usage: {{command:%s theme serve [ ROOT ]}}
|
113
124
|
|
114
125
|
Options:
|
115
|
-
{{command
|
116
|
-
{{command:--
|
117
|
-
{{command:--
|
118
|
-
{{command:--
|
119
|
-
{{command:--
|
120
|
-
|
121
|
-
|
122
|
-
|
126
|
+
{{command:-t, --theme=NAME_OR_ID}} Theme ID or name of the remote theme.
|
127
|
+
{{command:--port=PORT}} Local port to serve theme preview from.
|
128
|
+
{{command:--poll}} Force polling to detect file changes.
|
129
|
+
{{command:--host=HOST}} Set which network interface the web server listens on. The default value is 127.0.0.1.
|
130
|
+
{{command:--theme-editor-sync}} Synchronize Theme Editor updates in the local theme files.
|
131
|
+
{{command:--live-reload=MODE}} The live reload mode switches the server behavior when a file is modified:
|
132
|
+
- {{command:hot-reload}} Hot reloads local changes to CSS and sections (default)
|
133
|
+
- {{command:full-page}} Always refreshes the entire page
|
134
|
+
- {{command:off}} Deactivate live reload
|
123
135
|
HELP
|
124
136
|
reload_mode_is_not_valid: "The live reload mode `%s` is not valid.",
|
125
137
|
try_a_valid_reload_mode: "Try a valid live reload mode: %s.",
|
@@ -318,7 +330,8 @@ module Theme
|
|
318
330
|
HELP
|
319
331
|
select: "Select a theme to pull from",
|
320
332
|
pulling: "Pulling theme files from %s (#%s) on %s",
|
321
|
-
done: "Theme pulled successfully",
|
333
|
+
done: "Theme pulled successfully.",
|
334
|
+
done_with_errors: "{{warning:Your theme was pulled with errors.}}",
|
322
335
|
deprecated_themeid: <<~WARN,
|
323
336
|
{{warning:The {{command:-i, --themeid}} flag is deprecated. Use {{command:-t, --theme}} instead.}}
|
324
337
|
WARN
|
@@ -31,6 +31,7 @@ module ShopifyCLI
|
|
31
31
|
module EnvironmentVariables
|
32
32
|
STACKTRACE = "SHOPIFY_CLI_STACKTRACE"
|
33
33
|
TTY = "SHOPIFY_CLI_TTY"
|
34
|
+
RUN_AS_SUBPROCESS = "SHOPIFY_CLI_RUN_AS_SUBPROCESS"
|
34
35
|
|
35
36
|
# When true the CLI points to a local instance of
|
36
37
|
# the partners dashboard and identity.
|
@@ -54,6 +55,7 @@ module ShopifyCLI
|
|
54
55
|
# Authentication
|
55
56
|
AUTH_TOKEN = "SHOPIFY_CLI_AUTH_TOKEN"
|
56
57
|
ADMIN_AUTH_TOKEN = "SHOPIFY_CLI_ADMIN_AUTH_TOKEN"
|
58
|
+
STOREFRONT_RENDERER_AUTH_TOKEN = "SHOPIFY_CLI_STOREFRONT_RENDERER_AUTH_TOKEN"
|
57
59
|
|
58
60
|
# Monorail
|
59
61
|
MONORAIL_REAL_EVENTS = "MONORAIL_REAL_EVENTS"
|
data/lib/shopify_cli/context.rb
CHANGED
@@ -628,9 +628,10 @@ module ShopifyCLI
|
|
628
628
|
thread = Thread.new { retrieve_latest_gem_version }
|
629
629
|
at_exit { thread.join }
|
630
630
|
end
|
631
|
+
latest_version =
|
632
|
+
ShopifyCLI::Config.get(VERSION_CHECK_SECTION, LATEST_VERSION_FIELD, default: ShopifyCLI::VERSION)
|
633
|
+
latest_version if ::Semantic::Version.new(latest_version) > ::Semantic::Version.new(ShopifyCLI::VERSION)
|
631
634
|
end
|
632
|
-
latest_version = ShopifyCLI::Config.get(VERSION_CHECK_SECTION, LATEST_VERSION_FIELD, default: ShopifyCLI::VERSION)
|
633
|
-
latest_version if ::Semantic::Version.new(latest_version) > ::Semantic::Version.new(ShopifyCLI::VERSION)
|
634
635
|
end
|
635
636
|
|
636
637
|
# Returns file extension depending on OS
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module ShopifyCLI
|
2
|
+
module Core
|
3
|
+
##
|
4
|
+
# ShopifyCLI::Core::CliVersion checks that the CLI in use is correct for the project.
|
5
|
+
#
|
6
|
+
class CliVersion
|
7
|
+
class << self
|
8
|
+
def using_3_0?
|
9
|
+
!!cli_3_0_toml_dir
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def cli_3_0_toml_dir
|
15
|
+
Utilities.directory("shopify.app.toml", Dir.pwd)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -5,13 +5,27 @@ module ShopifyCLI
|
|
5
5
|
module EntryPoint
|
6
6
|
class << self
|
7
7
|
def call(args, ctx = Context.new)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
# Only instruct the user to update the CLI, or warn them that they're
|
9
|
+
# using CLI2 not CLI3, if they're running CLI2 directly. Otherwise the
|
10
|
+
# warnings will be confusing and/or incorrect.
|
11
|
+
unless Environment.run_as_subprocess?
|
12
|
+
if ctx.development? && !ctx.testing?
|
13
|
+
ctx.warn(
|
14
|
+
ctx.message(
|
15
|
+
"core.warning.development_version",
|
16
|
+
File.join(ShopifyCLI::ROOT, "bin", ShopifyCLI::TOOL_NAME)
|
17
|
+
)
|
18
|
+
)
|
19
|
+
# because `!ctx.new_version.nil?` will change the config by calling ::Config.set
|
20
|
+
# it's important to keep the checks in this order so that we don't trigger it while testing
|
21
|
+
# since changing the config will throw errors
|
22
|
+
elsif !ctx.testing? && !ctx.new_version.nil?
|
23
|
+
ctx.warn(ctx.message("core.warning.new_version", ShopifyCLI::VERSION, ctx.new_version))
|
24
|
+
end
|
25
|
+
|
26
|
+
if ShopifyCLI::Core::CliVersion.using_3_0?
|
27
|
+
ctx.warn(ctx.message("core.warning.in_3_0_directory"))
|
28
|
+
end
|
15
29
|
end
|
16
30
|
|
17
31
|
ProjectType.load_all
|
data/lib/shopify_cli/core.rb
CHANGED
@@ -170,6 +170,10 @@ module ShopifyCLI
|
|
170
170
|
env_variables[Constants::EnvironmentVariables::ADMIN_AUTH_TOKEN]
|
171
171
|
end
|
172
172
|
|
173
|
+
def self.storefront_renderer_auth_token(env_variables: ENV)
|
174
|
+
env_variables[Constants::EnvironmentVariables::STOREFRONT_RENDERER_AUTH_TOKEN]
|
175
|
+
end
|
176
|
+
|
173
177
|
def self.store(env_variables: ENV)
|
174
178
|
env_variables[Constants::EnvironmentVariables::STORE]
|
175
179
|
end
|
@@ -177,5 +181,12 @@ module ShopifyCLI
|
|
177
181
|
def self.env_variable_truthy?(variable_name, env_variables: ENV)
|
178
182
|
TRUTHY_ENV_VARIABLE_VALUES.include?(env_variables[variable_name.to_s])
|
179
183
|
end
|
184
|
+
|
185
|
+
def self.run_as_subprocess?(env_variables: ENV)
|
186
|
+
env_variable_truthy?(
|
187
|
+
Constants::EnvironmentVariables::RUN_AS_SUBPROCESS,
|
188
|
+
env_variables: env_variables
|
189
|
+
)
|
190
|
+
end
|
180
191
|
end
|
181
192
|
end
|
@@ -791,6 +791,16 @@ module ShopifyCLI
|
|
791
791
|
{{underline:https://shopify.dev/tools/cli/troubleshooting#upgrade-shopify-cli}}}}
|
792
792
|
|
793
793
|
MESSAGE
|
794
|
+
|
795
|
+
in_3_0_directory: <<~MESSAGE,
|
796
|
+
{{*}} {{yellow:You appear to be working with a CLI 3.0 project, but running a CLI 2.0 command. New syntax documentation: https://shopify.dev/apps/tools/cli/commands#command-syntax}}
|
797
|
+
|
798
|
+
For more information on CLI 3.0, see the documentation:
|
799
|
+
{{underline:https://shopify.dev/apps/tools/cli}}
|
800
|
+
|
801
|
+
Already have CLI 3.0 installed? Run it using your node package manager, as explained here:
|
802
|
+
{{underline:https://shopify.dev/apps/tools/cli/cli-2#running-shopify-cli-2-x-and-3-x-in-the-same-environment}}
|
803
|
+
MESSAGE
|
794
804
|
},
|
795
805
|
reporting: {
|
796
806
|
help: <<~HELP,
|
data/lib/shopify_cli/project.rb
CHANGED
@@ -119,18 +119,9 @@ module ShopifyCLI
|
|
119
119
|
private
|
120
120
|
|
121
121
|
def directory(dir)
|
122
|
-
@dir ||= Hash.new { |h, k| h[k] =
|
122
|
+
@dir ||= Hash.new { |h, k| h[k] = Utilities.directory(".shopify-cli.yml", k) }
|
123
123
|
@dir[dir]
|
124
124
|
end
|
125
|
-
|
126
|
-
def __directory(curr)
|
127
|
-
loop do
|
128
|
-
return nil if curr == "/" || /^[A-Z]:\/$/.match?(curr)
|
129
|
-
file = File.join(curr, ".shopify-cli.yml")
|
130
|
-
return curr if File.exist?(file)
|
131
|
-
curr = File.dirname(curr)
|
132
|
-
end
|
133
|
-
end
|
134
125
|
end
|
135
126
|
|
136
127
|
property :directory # :nodoc:
|
@@ -30,7 +30,7 @@ module ShopifyCLI
|
|
30
30
|
def parse(directory)
|
31
31
|
File.read(path(directory))
|
32
32
|
.gsub("\r\n", "\n").split("\n").each_with_object({}) do |line, output|
|
33
|
-
match = /\A([A-Za-z_0-9]+)\s*=\s*(.*)\z/.match(line)
|
33
|
+
match = /\A(#*\s*[A-Za-z_0-9]+)\s*=\s*(.*)\z/.match(line)
|
34
34
|
if match
|
35
35
|
key = match[1]
|
36
36
|
output[key] = case match[2]
|
@@ -14,7 +14,7 @@
|
|
14
14
|
function connect() {
|
15
15
|
const eventSource = new EventSource('/hot-reload');
|
16
16
|
|
17
|
-
eventSource.onmessage =
|
17
|
+
eventSource.onmessage = onMessage;
|
18
18
|
|
19
19
|
eventSource.onopen = () => console.log('[HotReload] SSE connected.');
|
20
20
|
|
@@ -97,10 +97,23 @@
|
|
97
97
|
window.location.reload();
|
98
98
|
}
|
99
99
|
|
100
|
-
function
|
101
|
-
|
100
|
+
function onMessage(message) {
|
101
|
+
const data = JSON.parse(message.data);
|
102
|
+
if (data.reload_page) {
|
103
|
+
refreshPage([]);
|
104
|
+
return;
|
105
|
+
}
|
106
|
+
|
107
|
+
handleUpdate(data);
|
108
|
+
}
|
109
|
+
|
110
|
+
function handleUpdate(data) {
|
102
111
|
var modifiedFiles = data.modified;
|
103
112
|
|
113
|
+
if (modifiedFiles === undefined) {
|
114
|
+
return;
|
115
|
+
}
|
116
|
+
|
104
117
|
if (isRefreshRequired(modifiedFiles)) {
|
105
118
|
refreshPage(modifiedFiles);
|
106
119
|
} else {
|
@@ -114,13 +127,15 @@
|
|
114
127
|
|
115
128
|
function reloadCssFile(filename) {
|
116
129
|
// Find a stylesheet link starting with /assets (locally-served only) containing the filename
|
117
|
-
let
|
130
|
+
let links = document.querySelectorAll(`link[href^="/assets"][href*="${filename}"][rel="stylesheet"]`);
|
118
131
|
|
119
|
-
if (!
|
132
|
+
if (!links.length) {
|
120
133
|
console.log(`[HotReload] Could not find link for stylesheet ${filename}`);
|
121
134
|
} else {
|
122
|
-
|
123
|
-
|
135
|
+
links.forEach(link => {
|
136
|
+
link.href = new URL(link.href).pathname + `?v=${Date.now()}`;
|
137
|
+
console.log(`[HotReload] Reloaded stylesheet ${filename}`);
|
138
|
+
})
|
124
139
|
}
|
125
140
|
}
|
126
141
|
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShopifyCLI
|
4
|
+
module Theme
|
5
|
+
module DevServer
|
6
|
+
class HotReload
|
7
|
+
class RemoteFileDeleter
|
8
|
+
def initialize(ctx, theme:, streams:)
|
9
|
+
@ctx = ctx
|
10
|
+
@theme = theme
|
11
|
+
@streams = streams
|
12
|
+
end
|
13
|
+
|
14
|
+
def delete(file)
|
15
|
+
retries = 6
|
16
|
+
|
17
|
+
until retries.zero?
|
18
|
+
retries -= 1
|
19
|
+
|
20
|
+
_status, body = fetch_asset(file)
|
21
|
+
retries = 0 if deleted_file?(body)
|
22
|
+
|
23
|
+
wait
|
24
|
+
end
|
25
|
+
|
26
|
+
notify(file)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def api_client
|
32
|
+
@api_client ||= ThemeAdminAPI.new(@ctx, @theme.shop)
|
33
|
+
end
|
34
|
+
|
35
|
+
def deleted_file?(body)
|
36
|
+
remote_checksum = body.dig("asset", "checksum")
|
37
|
+
|
38
|
+
remote_checksum.nil?
|
39
|
+
end
|
40
|
+
|
41
|
+
def notify(file)
|
42
|
+
@streams.broadcast(JSON.generate(deleted: [file]))
|
43
|
+
@ctx.debug("[RemoteFileDeleter] Deleted #{file}")
|
44
|
+
end
|
45
|
+
|
46
|
+
def wait
|
47
|
+
sleep(1)
|
48
|
+
end
|
49
|
+
|
50
|
+
def fetch_asset(file)
|
51
|
+
api_client.get(
|
52
|
+
path: "themes/#{@theme.id}/assets.json",
|
53
|
+
query: URI.encode_www_form("asset[key]" => file.relative_path),
|
54
|
+
)
|
55
|
+
rescue ShopifyCLI::API::APIRequestNotFoundError
|
56
|
+
[404, {}]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "hot_reload/remote_file_reloader"
|
4
|
+
require_relative "hot_reload/remote_file_deleter"
|
4
5
|
require_relative "hot_reload/sections_index"
|
5
6
|
|
6
7
|
module ShopifyCLI
|
@@ -14,6 +15,7 @@ module ShopifyCLI
|
|
14
15
|
@mode = mode
|
15
16
|
@streams = SSE::Streams.new
|
16
17
|
@remote_file_reloader = RemoteFileReloader.new(ctx, theme: @theme, streams: @streams)
|
18
|
+
@remote_file_deleter = RemoteFileDeleter.new(ctx, theme: @theme, streams: @streams)
|
17
19
|
@sections_index = SectionsIndex.new(@theme)
|
18
20
|
@watcher = watcher
|
19
21
|
@watcher.add_observer(self, :notify_streams_of_file_change)
|
@@ -36,13 +38,20 @@ module ShopifyCLI
|
|
36
38
|
@streams.close
|
37
39
|
end
|
38
40
|
|
39
|
-
def notify_streams_of_file_change(modified, added,
|
41
|
+
def notify_streams_of_file_change(modified, added, removed)
|
40
42
|
files = (modified + added)
|
41
|
-
.reject { |file| @ignore_filter&.ignore?(file) }
|
42
43
|
.map { |file| @theme[file] }
|
44
|
+
.reject { |file| @ignore_filter&.ignore?(file.relative_path) }
|
43
45
|
|
44
46
|
files -= liquid_css_files = files.select(&:liquid_css?)
|
45
47
|
|
48
|
+
deleted_files = removed
|
49
|
+
.map { |file| @theme[file] }
|
50
|
+
.reject { |file| @ignore_filter&.ignore?(file.relative_path) }
|
51
|
+
|
52
|
+
remote_delete(deleted_files) unless deleted_files.empty?
|
53
|
+
reload_page(removed) unless deleted_files.empty?
|
54
|
+
|
46
55
|
hot_reload(files) unless files.empty?
|
47
56
|
remote_reload(liquid_css_files)
|
48
57
|
end
|
@@ -55,8 +64,21 @@ module ShopifyCLI
|
|
55
64
|
@ctx.debug("[HotReload] Modified #{paths.join(", ")}")
|
56
65
|
end
|
57
66
|
|
67
|
+
def reload_page(removed)
|
68
|
+
@streams.broadcast(JSON.generate(reload_page: true))
|
69
|
+
@ctx.debug("[ReloadPage] Deleted #{removed.join(", ")}")
|
70
|
+
end
|
71
|
+
|
72
|
+
def remote_delete(files)
|
73
|
+
files.each do |file|
|
74
|
+
@ctx.debug("delete file each -> file.relative_path #{file.relative_path}")
|
75
|
+
@remote_file_deleter.delete(file)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
58
79
|
def remote_reload(files)
|
59
80
|
files.each do |file|
|
81
|
+
@ctx.debug("reload file each -> file.relative_path #{file.relative_path}")
|
60
82
|
@remote_file_reloader.reload(file)
|
61
83
|
end
|
62
84
|
end
|
@@ -382,7 +382,9 @@ module ShopifyCLI
|
|
382
382
|
rescue JSON::ParserError
|
383
383
|
[exception.message]
|
384
384
|
rescue StandardError => e
|
385
|
-
|
385
|
+
cause = "(cause: #{e.message})"
|
386
|
+
backtrace = e.backtrace.join("\n")
|
387
|
+
["The asset #{operation.file} could not be synced #{cause} #{backtrace}"]
|
386
388
|
end
|
387
389
|
|
388
390
|
def backoff_if_near_limit!(used, limit)
|
@@ -393,7 +395,11 @@ module ShopifyCLI
|
|
393
395
|
end
|
394
396
|
|
395
397
|
def overwrite_json?
|
396
|
-
@overwrite_json
|
398
|
+
theme_created_at_runtime? || @overwrite_json
|
399
|
+
end
|
400
|
+
|
401
|
+
def theme_created_at_runtime?
|
402
|
+
@theme.created_at_runtime?
|
397
403
|
end
|
398
404
|
|
399
405
|
def backingoff?
|
@@ -120,6 +120,7 @@ module ShopifyCLI
|
|
120
120
|
)
|
121
121
|
|
122
122
|
@id = body["theme"]["id"]
|
123
|
+
@created_at_runtime = true
|
123
124
|
end
|
124
125
|
|
125
126
|
def delete
|
@@ -147,6 +148,10 @@ module ShopifyCLI
|
|
147
148
|
development? && id != ShopifyCLI::DB.get(:development_theme_id)
|
148
149
|
end
|
149
150
|
|
151
|
+
def created_at_runtime?
|
152
|
+
@created_at_runtime ||= false
|
153
|
+
end
|
154
|
+
|
150
155
|
def to_h
|
151
156
|
{
|
152
157
|
id: id,
|
@@ -3,5 +3,14 @@ module ShopifyCLI
|
|
3
3
|
def self.version_dropping_pre_and_build(version)
|
4
4
|
Semantic::Version.new("#{version.major}.#{version.minor}.#{version.patch}")
|
5
5
|
end
|
6
|
+
|
7
|
+
def self.directory(pattern, curr)
|
8
|
+
loop do
|
9
|
+
return nil if curr == "/" || /^[A-Z]:\/$/.match?(curr)
|
10
|
+
file = File.join(curr, pattern)
|
11
|
+
return curr if File.exist?(file)
|
12
|
+
curr = File.dirname(curr)
|
13
|
+
end
|
14
|
+
end
|
6
15
|
end
|
7
16
|
end
|
data/lib/shopify_cli/version.rb
CHANGED
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.
|
4
|
+
version: 2.23.0
|
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-08-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -422,6 +422,7 @@ files:
|
|
422
422
|
- lib/shopify_cli/constants.rb
|
423
423
|
- lib/shopify_cli/context.rb
|
424
424
|
- lib/shopify_cli/core.rb
|
425
|
+
- lib/shopify_cli/core/cli_version.rb
|
425
426
|
- lib/shopify_cli/core/entry_point.rb
|
426
427
|
- lib/shopify_cli/core/executor.rb
|
427
428
|
- lib/shopify_cli/core/finalize.rb
|
@@ -507,6 +508,7 @@ files:
|
|
507
508
|
- lib/shopify_cli/theme/dev_server/hot-reload-no-script.html
|
508
509
|
- lib/shopify_cli/theme/dev_server/hot-reload.js
|
509
510
|
- lib/shopify_cli/theme/dev_server/hot_reload.rb
|
511
|
+
- lib/shopify_cli/theme/dev_server/hot_reload/remote_file_deleter.rb
|
510
512
|
- lib/shopify_cli/theme/dev_server/hot_reload/remote_file_reloader.rb
|
511
513
|
- lib/shopify_cli/theme/dev_server/hot_reload/sections_index.rb
|
512
514
|
- lib/shopify_cli/theme/dev_server/local_assets.rb
|