shopify-cli 2.11.0 → 2.11.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -1
- data/Gemfile.lock +1 -1
- data/lib/project_types/extension/commands/push.rb +13 -0
- data/lib/project_types/extension/loaders/project.rb +28 -8
- data/lib/project_types/extension/messages/messages.rb +10 -2
- data/lib/project_types/script/layers/application/create_script.rb +1 -1
- data/lib/project_types/script/layers/application/push_script.rb +1 -1
- data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_task_runner.rb +1 -8
- data/lib/project_types/script/layers/infrastructure/languages/task_runner.rb +35 -9
- data/lib/project_types/script/layers/infrastructure/languages/typescript_task_runner.rb +1 -8
- data/lib/project_types/script/layers/infrastructure/languages/wasm_task_runner.rb +3 -7
- data/lib/project_types/script/messages/messages.rb +6 -6
- data/lib/project_types/theme/commands/check.rb +0 -1
- data/lib/project_types/theme/commands/delete.rb +0 -1
- data/lib/project_types/theme/commands/init.rb +0 -1
- data/lib/project_types/theme/commands/language_server.rb +0 -1
- data/lib/project_types/theme/commands/package.rb +0 -1
- data/lib/project_types/theme/commands/publish.rb +0 -1
- data/lib/project_types/theme/commands/pull.rb +0 -1
- data/lib/project_types/theme/commands/push.rb +0 -1
- data/lib/project_types/theme/commands/serve.rb +0 -1
- data/lib/shopify_cli/command.rb +9 -3
- data/lib/shopify_cli/commands/app/create/rails.rb +1 -1
- data/lib/shopify_cli/commands/app/create.rb +0 -3
- data/lib/shopify_cli/commands/app/deploy.rb +0 -1
- data/lib/shopify_cli/commands/app/serve.rb +0 -1
- data/lib/shopify_cli/constants.rb +1 -1
- data/lib/shopify_cli/environment.rb +39 -45
- data/lib/shopify_cli/messages/messages.rb +1 -0
- data/lib/shopify_cli/theme/dev_server/hot_reload/remote_file_reloader.rb +63 -0
- data/lib/shopify_cli/theme/dev_server/hot_reload.rb +22 -6
- data/lib/shopify_cli/theme/dev_server/proxy.rb +4 -5
- data/lib/shopify_cli/theme/file.rb +4 -0
- data/lib/shopify_cli/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b4c9bb44a8b7b750acbf3364201705d93dfb39ce9772976ba2af04183cfc5748
|
4
|
+
data.tar.gz: fa32248af15c17d01d80132b4caf42ea224edba35146098954f51b4453db50de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3446d1a595e343f6566b7ec087c187d31518398ad57be75ff519a394133c75e4f0a5f8670d78913271091632d8ef9fdeef4fb1bb3c1b4ac5cb99d0bc12aef765
|
7
|
+
data.tar.gz: 48ad3c64a367e80facb7aecc393295fb8fa838949a51c7a71310c50a40e6bf2c648b57dbcaf53ade5e15af90ff911593e38865cbb8e2b8dce6b70a8918d83a03
|
data/CHANGELOG.md
CHANGED
@@ -2,8 +2,14 @@ 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.11.
|
5
|
+
## Version 2.11.1
|
6
|
+
### Fixed
|
7
|
+
* [#1973](https://github.com/Shopify/shopify-cli/pull/1973): Fix `theme serve` to preview generated files (`*.css.liquid`)
|
8
|
+
* [#2034](https://github.com/Shopify/shopify-cli/pull/2034): Fix `theme serve` to accept parameters with multiple values
|
9
|
+
* [#2033](https://github.com/Shopify/shopify-cli/pull/2033): Pin Homebrew Ruby to 3.0
|
10
|
+
* [#2032](https://github.com/Shopify/shopify-cli/pull/2032): Runtime error checking the Node version if Node is not present in the environment.
|
6
11
|
|
12
|
+
## Version 2.11.0
|
7
13
|
### Fixed
|
8
14
|
* [#2005](https://github.com/Shopify/shopify-cli/pull/2005): Fix PHP app serve on Windows environments
|
9
15
|
|
data/Gemfile.lock
CHANGED
@@ -27,6 +27,10 @@ module Extension
|
|
27
27
|
api_secret: options.flags[:api_secret],
|
28
28
|
registration_id: options.flags[:registration_id]
|
29
29
|
)
|
30
|
+
# on ci, registration id must be present
|
31
|
+
registration_id = options.flags[:registration_id]
|
32
|
+
check_registration(registration_id: registration_id, context: @ctx)
|
33
|
+
|
30
34
|
specification_handler = Extension::Loaders::SpecificationHandler.load(project: project, context: @ctx)
|
31
35
|
register_if_necessary(project: project, args: args, name: name)
|
32
36
|
|
@@ -43,6 +47,15 @@ module Extension
|
|
43
47
|
end
|
44
48
|
end
|
45
49
|
|
50
|
+
def check_registration(registration_id:, context:)
|
51
|
+
if !ShopifyCLI::Environment.interactive? && (!registration_id || registration_id.empty?)
|
52
|
+
message = context.message("errors.missing_push_options_ci", "--registration-id")
|
53
|
+
message += context.message("errors.missing_push_options_ci_solution", ShopifyCLI::TOOL_NAME)
|
54
|
+
raise ShopifyCLI::Abort,
|
55
|
+
message
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
46
59
|
def self.help
|
47
60
|
ShopifyCLI::Context.new.message("push.help", ShopifyCLI::TOOL_NAME)
|
48
61
|
end
|
@@ -9,20 +9,40 @@ module Extension
|
|
9
9
|
"SHOPIFY_API_SECRET" => api_secret,
|
10
10
|
"EXTENSION_ID" => registration_id,
|
11
11
|
}.compact
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
env_file_present = env_file_exists?(directory)
|
13
|
+
env = if env_file_present
|
14
|
+
ShopifyCLI::Resources::EnvFile.read(directory, overrides: env_overrides)
|
15
|
+
else
|
16
|
+
ShopifyCLI::Resources::EnvFile.from_hash(env_overrides)
|
17
|
+
end
|
18
18
|
# This is a somewhat uncomfortable hack we use because `Project::at` is
|
19
19
|
# a global cache and we can't rely on this class loading the project
|
20
20
|
# first. Long-term we should move away from that global cache.
|
21
21
|
project = ExtensionProject.at(directory)
|
22
22
|
project.env = env
|
23
23
|
project
|
24
|
-
rescue SmartProperties::InitializationError, SmartProperties::MissingValueError
|
25
|
-
|
24
|
+
rescue SmartProperties::InitializationError, SmartProperties::MissingValueError => error
|
25
|
+
handle_error(error, context: context)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.handle_error(error, context:)
|
29
|
+
if ShopifyCLI::Environment.interactive?
|
30
|
+
properties_hash = { api_key: "SHOPIFY_API_KEY", secret: "SHOPIFY_API_SECRET" }
|
31
|
+
missing_env_variables = error.properties.map { |p| properties_hash[p.name] }.compact.join(", ")
|
32
|
+
message = context.message("errors.missing_env_file_variables", missing_env_variables)
|
33
|
+
message += context.message("errors.missing_env_file_variables_solution", ShopifyCLI::TOOL_NAME)
|
34
|
+
else
|
35
|
+
properties_hash = { api_key: "--api-key", secret: "--api-secret" }
|
36
|
+
missing_options = error.properties.map { |p| properties_hash[p.name] }.compact.join(", ")
|
37
|
+
message = context.message("errors.missing_push_options_ci", missing_options)
|
38
|
+
message += context.message("errors.missing_push_options_ci_solution", ShopifyCLI::TOOL_NAME)
|
39
|
+
end
|
40
|
+
raise ShopifyCLI::Abort,
|
41
|
+
message
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.env_file_exists?(directory)
|
45
|
+
File.exist?(ShopifyCLI::Resources::EnvFile.path(directory))
|
26
46
|
end
|
27
47
|
end
|
28
48
|
end
|
@@ -174,9 +174,17 @@ module Extension
|
|
174
174
|
},
|
175
175
|
},
|
176
176
|
errors: {
|
177
|
-
unknown_type: "Unknown extension type %s"
|
177
|
+
unknown_type: "Unknown extension type %s. Valid extension types include: CHECKOUT_POST_PURCHASE, " \
|
178
|
+
"CHECKOUT_UI_EXTENSION, THEME_APP_EXTENSION, and PRODUCT_SUBSCRIPTION.",
|
178
179
|
package_not_found: "`%s` package not found.",
|
179
|
-
|
180
|
+
missing_push_options_ci: "The following are missing: %s. ",
|
181
|
+
missing_push_options_ci_solution: "To add them to a CI environment:\n\t1. Run a connect command " \
|
182
|
+
"({{command:%1$s extension connect}})\n\t2. Navigate to the .env file at the root of your project\n\t" \
|
183
|
+
"3. Copy the missing values and pass them through as arguments in {{command:%1$s extension push}}",
|
184
|
+
missing_env_file_variables: "The following are missing in the .env file: %s. ",
|
185
|
+
missing_env_file_variables_solution: "To add it, connect your extension with " \
|
186
|
+
"{{command:%1$s extension connect}} " \
|
187
|
+
"or run {{command:%1$s extension register}} to register a new extension.",
|
180
188
|
module_not_found: "Unable to find module %s. Ensure your dependencies are up-to-date and try again.",
|
181
189
|
},
|
182
190
|
warnings: {
|
@@ -47,7 +47,7 @@ module Script
|
|
47
47
|
private
|
48
48
|
|
49
49
|
def install_dependencies(ctx, language, script_name, project_creator)
|
50
|
-
task_runner = Infrastructure::Languages::TaskRunner.for(ctx, language
|
50
|
+
task_runner = Infrastructure::Languages::TaskRunner.for(ctx, language)
|
51
51
|
CLI::UI::Frame.open(ctx.message(
|
52
52
|
"core.git.pulling_from_to",
|
53
53
|
project_creator.sparse_checkout_repo,
|
@@ -10,7 +10,7 @@ module Script
|
|
10
10
|
script_project = script_project_repo.get
|
11
11
|
script_project.env = project.env
|
12
12
|
task_runner = Infrastructure::Languages::TaskRunner
|
13
|
-
.for(ctx, script_project.language
|
13
|
+
.for(ctx, script_project.language)
|
14
14
|
|
15
15
|
extension_point = ExtensionPoints.get(type: script_project.extension_point_type)
|
16
16
|
|
@@ -4,18 +4,11 @@ module Script
|
|
4
4
|
module Layers
|
5
5
|
module Infrastructure
|
6
6
|
module Languages
|
7
|
-
class AssemblyScriptTaskRunner
|
7
|
+
class AssemblyScriptTaskRunner < TaskRunner
|
8
8
|
BYTECODE_FILE = "build/script.wasm"
|
9
9
|
METADATA_FILE = "build/metadata.json"
|
10
10
|
SCRIPT_SDK_BUILD = "npm run build"
|
11
11
|
|
12
|
-
attr_reader :ctx, :script_name
|
13
|
-
|
14
|
-
def initialize(ctx, script_name)
|
15
|
-
@ctx = ctx
|
16
|
-
@script_name = script_name
|
17
|
-
end
|
18
|
-
|
19
12
|
def build
|
20
13
|
compile
|
21
14
|
bytecode
|
@@ -5,15 +5,41 @@ module Script
|
|
5
5
|
module Infrastructure
|
6
6
|
module Languages
|
7
7
|
class TaskRunner
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
8
|
+
attr_reader :ctx
|
9
|
+
|
10
|
+
def self.for(ctx, language)
|
11
|
+
task_runners = {
|
12
|
+
"assemblyscript" => AssemblyScriptTaskRunner,
|
13
|
+
"typescript" => TypeScriptTaskRunner,
|
14
|
+
"wasm" => WasmTaskRunner,
|
15
|
+
}
|
16
|
+
|
17
|
+
raise Errors::TaskRunnerNotFoundError unless task_runners[language]
|
18
|
+
task_runners[language].new(ctx)
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(ctx)
|
22
|
+
@ctx = ctx
|
23
|
+
end
|
24
|
+
|
25
|
+
def build
|
26
|
+
raise NotImplementedError
|
27
|
+
end
|
28
|
+
|
29
|
+
def dependencies_installed?
|
30
|
+
raise NotImplementedError
|
31
|
+
end
|
32
|
+
|
33
|
+
def install_dependencies
|
34
|
+
raise NotImplementedError
|
35
|
+
end
|
36
|
+
|
37
|
+
def metadata_file_location
|
38
|
+
raise NotImplementedError
|
39
|
+
end
|
40
|
+
|
41
|
+
def library_version(_library_name)
|
42
|
+
raise NotImplementedError
|
17
43
|
end
|
18
44
|
end
|
19
45
|
end
|
@@ -4,19 +4,12 @@ module Script
|
|
4
4
|
module Layers
|
5
5
|
module Infrastructure
|
6
6
|
module Languages
|
7
|
-
class TypeScriptTaskRunner
|
7
|
+
class TypeScriptTaskRunner < TaskRunner
|
8
8
|
BYTECODE_FILE = "build/index.wasm"
|
9
9
|
METADATA_FILE = "build/metadata.json"
|
10
10
|
SCRIPT_SDK_BUILD = "npm run build"
|
11
11
|
GEN_METADATA = "npm run gen-metadata"
|
12
12
|
|
13
|
-
attr_reader :ctx, :script_name
|
14
|
-
|
15
|
-
def initialize(ctx, script_name)
|
16
|
-
@ctx = ctx
|
17
|
-
@script_name = script_name
|
18
|
-
end
|
19
|
-
|
20
13
|
def build
|
21
14
|
compile
|
22
15
|
bytecode
|
@@ -4,19 +4,15 @@ module Script
|
|
4
4
|
module Layers
|
5
5
|
module Infrastructure
|
6
6
|
module Languages
|
7
|
-
class WasmTaskRunner
|
7
|
+
class WasmTaskRunner < TaskRunner
|
8
8
|
BYTECODE_FILE = "script.wasm"
|
9
|
-
attr_reader :ctx, :script_name
|
10
|
-
|
11
|
-
def initialize(ctx, script_name)
|
12
|
-
@ctx = ctx
|
13
|
-
@script_name = script_name
|
14
|
-
end
|
15
9
|
|
16
10
|
def dependencies_installed?
|
17
11
|
true
|
18
12
|
end
|
19
13
|
|
14
|
+
def install_dependencies; end
|
15
|
+
|
20
16
|
def library_version(_library_name)
|
21
17
|
nil
|
22
18
|
end
|
@@ -149,12 +149,12 @@ module Script
|
|
149
149
|
|
150
150
|
language_library_for_api_not_found_cause: "Script can’t be pushed because the %{language} library for API %{api} is missing.",
|
151
151
|
language_library_for_api_not_found_help: "Make sure extension_point.yml contains the correct API library.",
|
152
|
-
no_scripts_found_in_app: "The selected apps have no scripts.
|
153
|
-
missing_env_file_variables: "The following
|
154
|
-
"
|
155
|
-
|
156
|
-
|
157
|
-
"
|
152
|
+
no_scripts_found_in_app: "The selected apps have no scripts. Please, create them first on the partners' dashboard.",
|
153
|
+
missing_env_file_variables: "The following are missing in the .env file: %s."\
|
154
|
+
" To add it, run {{command:%s script connect}}",
|
155
|
+
missing_push_options: "The following are missing: %s. "\
|
156
|
+
"To add them to a CI environment:\n\t1. Run a connect command {{command:%s script connect}}\n\t2. Navigate to the .env file at the root of your project\n\t"\
|
157
|
+
"3. Copy the missing values, then pass them through as arguments.",
|
158
158
|
},
|
159
159
|
|
160
160
|
create: {
|
data/lib/shopify_cli/command.rb
CHANGED
@@ -100,14 +100,20 @@ module ShopifyCLI
|
|
100
100
|
end
|
101
101
|
|
102
102
|
def check_node_version
|
103
|
+
context = Context.new
|
104
|
+
if @compatible_node_range && context.which("node").nil?
|
105
|
+
raise ShopifyCLI::Abort, context.message("core.errors.missing_node")
|
106
|
+
end
|
107
|
+
|
103
108
|
check_version(
|
104
109
|
Environment.node_version,
|
105
110
|
range: @compatible_node_range,
|
106
|
-
runtime: "Node"
|
111
|
+
runtime: "Node",
|
112
|
+
context: context
|
107
113
|
)
|
108
114
|
end
|
109
115
|
|
110
|
-
def check_version(version, range:, runtime:)
|
116
|
+
def check_version(version, range:, runtime:, context: Context.new)
|
111
117
|
return if Environment.test?
|
112
118
|
return if range.nil?
|
113
119
|
|
@@ -116,7 +122,7 @@ module ShopifyCLI
|
|
116
122
|
is_lower_than_top = version_without_pre_nor_build < Utilities.version_dropping_pre_and_build(range.to)
|
117
123
|
return if is_higher_than_bottom && is_lower_than_top
|
118
124
|
|
119
|
-
|
125
|
+
context.warn("Your environment #{runtime} version, #{version},"\
|
120
126
|
" is outside of the range supported by the CLI,"\
|
121
127
|
" #{range.from}..<#{range.to},"\
|
122
128
|
" and might cause incompatibility issues.")
|
@@ -5,8 +5,8 @@ module ShopifyCLI
|
|
5
5
|
class Rails < ShopifyCLI::Command::AppSubCommand
|
6
6
|
prerequisite_task :ensure_authenticated
|
7
7
|
|
8
|
-
recommend_default_node_range
|
9
8
|
recommend_default_ruby_range
|
9
|
+
recommend_default_node_range
|
10
10
|
|
11
11
|
options do |parser, flags|
|
12
12
|
parser.on("--name=NAME") { |t| flags[:name] = t }
|
@@ -6,9 +6,6 @@ module ShopifyCLI
|
|
6
6
|
subcommand :PHP, "php", "shopify_cli/commands/app/create/php"
|
7
7
|
subcommand :Node, "node", "shopify_cli/commands/app/create/node"
|
8
8
|
|
9
|
-
recommend_default_node_range
|
10
|
-
recommend_default_ruby_range
|
11
|
-
|
12
9
|
def call(_args, _command_name)
|
13
10
|
@ctx.puts(self.class.help)
|
14
11
|
end
|
@@ -38,7 +38,7 @@ module ShopifyCLI
|
|
38
38
|
|
39
39
|
# When true the CLI points to spin instances of services
|
40
40
|
SPIN = "SPIN"
|
41
|
-
|
41
|
+
SPIN_INSTANCE = "SPIN_INSTANCE"
|
42
42
|
SPIN_WORKSPACE = "SPIN_WORKSPACE"
|
43
43
|
SPIN_NAMESPACE = "SPIN_NAMESPACE"
|
44
44
|
SPIN_HOST = "SPIN_HOST"
|
@@ -5,6 +5,11 @@ module ShopifyCLI
|
|
5
5
|
# the environment in which the CLI runs
|
6
6
|
module Environment
|
7
7
|
TRUTHY_ENV_VARIABLE_VALUES = ["1", "true", "TRUE", "yes", "YES"]
|
8
|
+
SPIN_OVERRIDE_ENV_NAMES = [
|
9
|
+
Constants::EnvironmentVariables::SPIN_WORKSPACE,
|
10
|
+
Constants::EnvironmentVariables::SPIN_NAMESPACE,
|
11
|
+
Constants::EnvironmentVariables::SPIN_HOST,
|
12
|
+
]
|
8
13
|
|
9
14
|
def self.ruby_version(context: Context.new)
|
10
15
|
out, err, stat = context.capture3('ruby -e "puts RUBY_VERSION"')
|
@@ -87,6 +92,20 @@ module ShopifyCLI
|
|
87
92
|
end
|
88
93
|
end
|
89
94
|
|
95
|
+
def self.spin_url_override(env_variables: ENV)
|
96
|
+
tokens = SPIN_OVERRIDE_ENV_NAMES.map do |name|
|
97
|
+
env_variables[name]
|
98
|
+
end
|
99
|
+
|
100
|
+
return if tokens.all?(&:nil?)
|
101
|
+
|
102
|
+
if tokens.any?(&:nil?)
|
103
|
+
raise "To manually target a spin instance, you must set #{SPIN_OVERRIDE_ENV_NAMES}"
|
104
|
+
else
|
105
|
+
tokens.join(".")
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
90
109
|
def self.use_spin?(env_variables: ENV)
|
91
110
|
env_variable_truthy?(
|
92
111
|
Constants::EnvironmentVariables::SPIN,
|
@@ -97,32 +116,29 @@ module ShopifyCLI
|
|
97
116
|
)
|
98
117
|
end
|
99
118
|
|
100
|
-
def self.infer_spin?(env_variables: ENV)
|
101
|
-
env_variable_truthy?(
|
102
|
-
Constants::EnvironmentVariables::INFER_SPIN,
|
103
|
-
env_variables: env_variables
|
104
|
-
)
|
105
|
-
end
|
106
|
-
|
107
119
|
def self.spin_url(env_variables: ENV)
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
%x(spin show -o fqdn 2> /dev/null).strip
|
116
|
-
else
|
117
|
-
# spin-legacy
|
118
|
-
%x(spin info fqdn 2> /dev/null).strip
|
119
|
-
end
|
120
|
+
override = spin_url_override(env_variables: env_variables)
|
121
|
+
return override unless override.nil?
|
122
|
+
|
123
|
+
spin_response = if env_variables.key?(
|
124
|
+
Constants::EnvironmentVariables::SPIN_INSTANCE
|
125
|
+
)
|
126
|
+
spin_show
|
120
127
|
else
|
121
|
-
|
122
|
-
spin_namespace = spin_namespace(env_variables: env_variables)
|
123
|
-
spin_host = spin_host(env_variables: env_variables)
|
124
|
-
"#{spin_workspace}.#{spin_namespace}.#{spin_host}"
|
128
|
+
spin_show(latest: true)
|
125
129
|
end
|
130
|
+
|
131
|
+
begin
|
132
|
+
instance = JSON.parse(spin_response)
|
133
|
+
raise "Missing key 'fqdn' from spin show. Actual response: #{instance}" unless instance.include?("fqdn")
|
134
|
+
instance["fqdn"]
|
135
|
+
rescue => e
|
136
|
+
raise "Failed to infer spin environment from spin show response #{spin_response}: #{e}"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def self.spin_show(latest: false)
|
141
|
+
latest ? %x(spin show --latest --json) : %x(spin show --json)
|
126
142
|
end
|
127
143
|
|
128
144
|
def self.send_monorail_events?(env_variables: ENV)
|
@@ -139,27 +155,5 @@ module ShopifyCLI
|
|
139
155
|
def self.env_variable_truthy?(variable_name, env_variables: ENV)
|
140
156
|
TRUTHY_ENV_VARIABLE_VALUES.include?(env_variables[variable_name.to_s])
|
141
157
|
end
|
142
|
-
|
143
|
-
def self.spin_workspace(env_variables: ENV)
|
144
|
-
env_value = env_variables[Constants::EnvironmentVariables::SPIN_WORKSPACE]
|
145
|
-
return env_value unless env_value.nil?
|
146
|
-
|
147
|
-
if env_value.nil?
|
148
|
-
raise "No value set for #{Constants::EnvironmentVariables::SPIN_WORKSPACE}"
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
def self.spin_namespace(env_variables: ENV)
|
153
|
-
env_value = env_variables[Constants::EnvironmentVariables::SPIN_NAMESPACE]
|
154
|
-
return env_value unless env_value.nil?
|
155
|
-
|
156
|
-
if env_value.nil?
|
157
|
-
raise "No value set for #{Constants::EnvironmentVariables::SPIN_NAMESPACE}"
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
def self.spin_host(env_variables: ENV)
|
162
|
-
env_variables[Constants::EnvironmentVariables::SPIN_HOST] || "us.spin.dev"
|
163
|
-
end
|
164
158
|
end
|
165
159
|
end
|
@@ -15,6 +15,7 @@ module ShopifyCLI
|
|
15
15
|
},
|
16
16
|
core: {
|
17
17
|
errors: {
|
18
|
+
missing_node: "Node is necessary for this command and was not found in the environment.",
|
18
19
|
option_parser: {
|
19
20
|
invalid_option: "The option {{command:%s}} is not supported.",
|
20
21
|
missing_argument: "The required argument {{command:%s}} is missing.",
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ShopifyCLI
|
4
|
+
module Theme
|
5
|
+
module DevServer
|
6
|
+
class HotReload
|
7
|
+
class RemoteFileReloader
|
8
|
+
def initialize(ctx, theme:, streams:)
|
9
|
+
@ctx = ctx
|
10
|
+
@theme = theme
|
11
|
+
@streams = streams
|
12
|
+
end
|
13
|
+
|
14
|
+
def reload(file)
|
15
|
+
retries = 6
|
16
|
+
|
17
|
+
until retries.zero?
|
18
|
+
retries -= 1
|
19
|
+
|
20
|
+
_status, body = fetch_asset(file)
|
21
|
+
retries = 0 if updated_file?(body, file)
|
22
|
+
|
23
|
+
wait
|
24
|
+
end
|
25
|
+
|
26
|
+
notify(file)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def updated_file?(body, file)
|
32
|
+
remote_checksum = body.dig("asset", "checksum")
|
33
|
+
local_checksum = file.checksum
|
34
|
+
|
35
|
+
remote_checksum == local_checksum
|
36
|
+
end
|
37
|
+
|
38
|
+
def notify(file)
|
39
|
+
@streams.broadcast(JSON.generate(modified: [file]))
|
40
|
+
@ctx.debug("[RemoteFileReloader] Modified #{file}")
|
41
|
+
end
|
42
|
+
|
43
|
+
def wait
|
44
|
+
sleep(1)
|
45
|
+
end
|
46
|
+
|
47
|
+
def fetch_asset(file)
|
48
|
+
ShopifyCLI::AdminAPI.rest_request(
|
49
|
+
@ctx,
|
50
|
+
shop: @theme.shop,
|
51
|
+
path: "themes/#{@theme.id}/assets.json",
|
52
|
+
method: "GET",
|
53
|
+
api_version: "unstable",
|
54
|
+
query: URI.encode_www_form("asset[key]" => file.relative_path.to_s),
|
55
|
+
)
|
56
|
+
rescue ShopifyCLI::API::APIRequestNotFoundError
|
57
|
+
[404, {}]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "hot_reload/remote_file_reloader"
|
4
|
+
|
3
5
|
module ShopifyCLI
|
4
6
|
module Theme
|
5
7
|
module DevServer
|
@@ -10,6 +12,7 @@ module ShopifyCLI
|
|
10
12
|
@theme = theme
|
11
13
|
@mode = mode
|
12
14
|
@streams = SSE::Streams.new
|
15
|
+
@remote_file_reloader = RemoteFileReloader.new(ctx, theme: @theme, streams: @streams)
|
13
16
|
@watcher = watcher
|
14
17
|
@watcher.add_observer(self, :notify_streams_of_file_change)
|
15
18
|
@ignore_filter = ignore_filter
|
@@ -32,17 +35,30 @@ module ShopifyCLI
|
|
32
35
|
end
|
33
36
|
|
34
37
|
def notify_streams_of_file_change(modified, added, _removed)
|
35
|
-
files = (modified + added)
|
36
|
-
.
|
38
|
+
files = (modified + added)
|
39
|
+
.reject { |file| @ignore_filter&.ignore?(file) }
|
40
|
+
.map { |file| @theme[file] }
|
37
41
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
+
files -= liquid_css_files = files.select(&:liquid_css?)
|
43
|
+
|
44
|
+
hot_reload(files) unless files.empty?
|
45
|
+
remote_reload(liquid_css_files)
|
42
46
|
end
|
43
47
|
|
44
48
|
private
|
45
49
|
|
50
|
+
def hot_reload(files)
|
51
|
+
paths = files.map(&:relative_path)
|
52
|
+
@streams.broadcast(JSON.generate(modified: paths))
|
53
|
+
@ctx.debug("[HotReload] Modified #{paths.join(", ")}")
|
54
|
+
end
|
55
|
+
|
56
|
+
def remote_reload(files)
|
57
|
+
files.each do |file|
|
58
|
+
@remote_file_reloader.reload(file)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
46
62
|
def request_is_html?(headers)
|
47
63
|
headers["content-type"]&.start_with?("text/html")
|
48
64
|
end
|
@@ -43,9 +43,8 @@ module ShopifyCLI
|
|
43
43
|
headers["Accept-Encoding"] = "none"
|
44
44
|
headers["User-Agent"] = "Shopify CLI"
|
45
45
|
|
46
|
-
query = URI.decode_www_form(env["QUERY_STRING"])
|
46
|
+
query = URI.decode_www_form(env["QUERY_STRING"])
|
47
47
|
replace_templates = build_replace_templates_param(env)
|
48
|
-
|
49
48
|
response = if replace_templates.any?
|
50
49
|
# Pass to SFR the recently modified templates in `replace_templates` body param
|
51
50
|
headers["Authorization"] = "Bearer #{bearer_token}"
|
@@ -158,7 +157,7 @@ module ShopifyCLI
|
|
158
157
|
def secure_session_id
|
159
158
|
if secure_session_id_expired?
|
160
159
|
@ctx.debug("Refreshing preview _secure_session_id cookie")
|
161
|
-
response = request("HEAD", "/", query:
|
160
|
+
response = request("HEAD", "/", query: [[:preview_theme_id, @theme.id]])
|
162
161
|
@secure_session_id = extract_secure_session_id_from_response_headers(response)
|
163
162
|
@last_session_cookie_refresh = Time.now
|
164
163
|
end
|
@@ -189,9 +188,9 @@ module ShopifyCLI
|
|
189
188
|
response_headers
|
190
189
|
end
|
191
190
|
|
192
|
-
def request(method, path, headers: nil, query:
|
191
|
+
def request(method, path, headers: nil, query: [], form_data: nil, body_stream: nil)
|
193
192
|
uri = URI.join("https://#{@theme.shop}", path)
|
194
|
-
uri.query = URI.encode_www_form(query
|
193
|
+
uri.query = URI.encode_www_form(query + [[:_fd, 0], [:pb, 0]])
|
195
194
|
|
196
195
|
@ctx.debug("Proxying #{method} #{uri}")
|
197
196
|
|
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.11.
|
4
|
+
version: 2.11.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-02-
|
11
|
+
date: 2022-02-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -469,6 +469,7 @@ files:
|
|
469
469
|
- lib/shopify_cli/theme/dev_server/header_hash.rb
|
470
470
|
- lib/shopify_cli/theme/dev_server/hot-reload.js
|
471
471
|
- lib/shopify_cli/theme/dev_server/hot_reload.rb
|
472
|
+
- lib/shopify_cli/theme/dev_server/hot_reload/remote_file_reloader.rb
|
472
473
|
- lib/shopify_cli/theme/dev_server/local_assets.rb
|
473
474
|
- lib/shopify_cli/theme/dev_server/proxy.rb
|
474
475
|
- lib/shopify_cli/theme/dev_server/proxy/template_param_builder.rb
|