shopify-cli 2.16.1 → 2.18.1
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/CHANGELOG.md +26 -0
- data/Gemfile.lock +3 -3
- data/ext/shopify-extensions/version +1 -1
- data/lib/project_types/extension/cli.rb +1 -0
- data/lib/project_types/extension/commands/build.rb +0 -2
- data/lib/project_types/extension/commands/serve.rb +8 -3
- data/lib/project_types/extension/features/argo_serve.rb +1 -1
- data/lib/project_types/extension/forms/questions/ask_template.rb +3 -3
- data/lib/project_types/extension/messages/messages.rb +16 -0
- data/lib/project_types/extension/models/development_server_requirements.rb +1 -1
- data/lib/project_types/extension/models/server_config/capabilities.rb +11 -0
- data/lib/project_types/extension/models/server_config/development.rb +9 -0
- data/lib/project_types/extension/models/server_config/development_renderer.rb +2 -0
- data/lib/project_types/extension/models/server_config/extension.rb +10 -3
- data/lib/project_types/extension/models/specification_handlers/checkout_ui_extension.rb +1 -1
- data/lib/project_types/extension/models/specification_handlers/{beacon_extension.rb → web_pixel_extension.rb} +11 -10
- data/lib/project_types/extension/models/specification_handlers/{beacon_extension_utils → web_pixel_extension_utils}/script_config.rb +1 -1
- data/lib/project_types/extension/models/specification_handlers/{beacon_extension_utils → web_pixel_extension_utils}/script_config_repository.rb +2 -2
- data/lib/project_types/extension/tasks/configure_options.rb +1 -1
- data/lib/project_types/extension/tasks/convert_server_config.rb +8 -4
- data/lib/project_types/extension/tasks/execute_commands/outdated_extension_detection.rb +5 -1
- data/lib/project_types/extension/tasks/merge_server_config.rb +4 -2
- data/lib/project_types/script/cli.rb +1 -0
- data/lib/project_types/script/config/extension_points.yml +20 -18
- data/lib/project_types/script/graphql/app_script_set.graphql +2 -0
- data/lib/project_types/script/layers/application/push_script.rb +1 -0
- data/lib/project_types/script/layers/domain/app_bridge.rb +16 -0
- data/lib/project_types/script/layers/domain/script_project.rb +1 -0
- data/lib/project_types/script/layers/infrastructure/errors.rb +11 -0
- data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +15 -1
- data/lib/project_types/script/layers/infrastructure/script_service.rb +9 -0
- data/lib/project_types/script/messages/messages.rb +4 -1
- data/lib/project_types/script/ui/error_handler.rb +8 -0
- data/lib/project_types/theme/commands/delete.rb +1 -0
- data/lib/project_types/theme/commands/open.rb +6 -1
- data/lib/project_types/theme/commands/publish.rb +1 -0
- data/lib/project_types/theme/commands/serve.rb +28 -0
- data/lib/project_types/theme/forms/select.rb +4 -1
- data/lib/project_types/theme/messages/messages.rb +33 -3
- data/lib/shopify_cli/admin_api.rb +1 -1
- data/lib/shopify_cli/commands/login.rb +2 -2
- data/lib/shopify_cli/context.rb +1 -1
- data/lib/shopify_cli/core/monorail.rb +1 -1
- data/lib/shopify_cli/git.rb +7 -2
- data/lib/shopify_cli/heroku.rb +5 -3
- data/lib/shopify_cli/messages/messages.rb +1 -1
- data/lib/shopify_cli/release.rb +5 -2
- data/lib/shopify_cli/services/app/create/node_service.rb +1 -1
- data/lib/shopify_cli/services/app/create/php_service.rb +1 -1
- data/lib/shopify_cli/theme/dev_server/hot_reload/sections_index.rb +5 -6
- data/lib/shopify_cli/theme/dev_server/watcher.rb +2 -1
- data/lib/shopify_cli/theme/dev_server.rb +20 -3
- data/lib/shopify_cli/theme/development_theme.rb +11 -1
- data/lib/shopify_cli/theme/file.rb +9 -0
- data/lib/shopify_cli/theme/syncer/forms/select_update_strategy.rb +2 -2
- data/lib/shopify_cli/theme/syncer/json_update_handler.rb +1 -1
- data/lib/shopify_cli/theme/theme_admin_api.rb +3 -1
- data/lib/shopify_cli/version.rb +1 -1
- metadata +7 -5
@@ -37,7 +37,9 @@ module Script
|
|
37
37
|
extension_point_type: extension_point_type,
|
38
38
|
title: title,
|
39
39
|
description: nil,
|
40
|
-
language: language
|
40
|
+
language: language,
|
41
|
+
app_bridge_create_path: "/",
|
42
|
+
app_bridge_details_path: "/",
|
41
43
|
)
|
42
44
|
|
43
45
|
build_script_project(script_config: nil)
|
@@ -54,6 +56,7 @@ module Script
|
|
54
56
|
extension_point_type: extension_point_type,
|
55
57
|
language: language,
|
56
58
|
script_config: script_config_repository.get!,
|
59
|
+
app_bridge: app_bridge,
|
57
60
|
input_query: read_input_query,
|
58
61
|
)
|
59
62
|
end
|
@@ -94,6 +97,7 @@ module Script
|
|
94
97
|
extension_point_type: extension_point_type,
|
95
98
|
language: language,
|
96
99
|
script_config: script_config,
|
100
|
+
app_bridge: app_bridge,
|
97
101
|
)
|
98
102
|
end
|
99
103
|
|
@@ -121,6 +125,16 @@ module Script
|
|
121
125
|
project_config_value("language")&.downcase || default_language
|
122
126
|
end
|
123
127
|
|
128
|
+
def app_bridge
|
129
|
+
create_path = project_config_value!("app_bridge_create_path")
|
130
|
+
details_path = project_config_value!("app_bridge_details_path")
|
131
|
+
|
132
|
+
Domain::AppBridge.new(
|
133
|
+
create_path: create_path,
|
134
|
+
details_path: details_path,
|
135
|
+
)
|
136
|
+
end
|
137
|
+
|
124
138
|
def project_config_value(key)
|
125
139
|
return nil unless project.config.key?(key)
|
126
140
|
project.config[key]
|
@@ -20,6 +20,7 @@ module Script
|
|
20
20
|
force: false,
|
21
21
|
metadata:,
|
22
22
|
script_config:,
|
23
|
+
app_bridge:,
|
23
24
|
module_upload_url:,
|
24
25
|
library:,
|
25
26
|
input_query: nil
|
@@ -36,6 +37,10 @@ module Script
|
|
36
37
|
scriptConfigVersion: script_config.version,
|
37
38
|
configurationUi: script_config.configuration_ui,
|
38
39
|
configurationDefinition: script_config.configuration&.to_json,
|
40
|
+
appBridge: {
|
41
|
+
createPath: app_bridge.create_path,
|
42
|
+
detailsPath: app_bridge.details_path,
|
43
|
+
},
|
39
44
|
moduleUploadUrl: module_upload_url,
|
40
45
|
inputQuery: input_query,
|
41
46
|
}
|
@@ -87,6 +92,10 @@ module Script
|
|
87
92
|
raise Errors::InvalidInputQueryErrors, errors.map { |err| err["message"] }
|
88
93
|
elsif user_errors.find { |err| %w(not_use_msgpack_error schema_version_argument_error).include?(err["tag"]) }
|
89
94
|
raise Domain::Errors::MetadataValidationError
|
95
|
+
elsif user_errors.find { |err| err["tag"] == "invalid_app_bridge_create_path" }
|
96
|
+
raise Errors::InvalidAppBridgePathError, "create"
|
97
|
+
elsif user_errors.find { |err| err["tag"] == "invalid_app_bridge_details_path" }
|
98
|
+
raise Errors::InvalidAppBridgePathError, "details"
|
90
99
|
else
|
91
100
|
raise Errors::GraphqlError, user_errors
|
92
101
|
end
|
@@ -24,7 +24,7 @@ module Script
|
|
24
24
|
oauth_help: "Wait a few minutes and try again.",
|
25
25
|
|
26
26
|
invalid_context_cause: "Your .shopify-cli.yml is formatted incorrectly. It's missing values for "\
|
27
|
-
"extension_point_type or
|
27
|
+
"extension_point_type, title, app_bridge_create_path or app_bridge_details_path.",
|
28
28
|
invalid_context_help: "Add these values.",
|
29
29
|
|
30
30
|
invalid_script_title_cause: "Script title contains unsupported characters.",
|
@@ -164,6 +164,9 @@ module Script
|
|
164
164
|
missing_env_file_variables: "The following are missing in the .env file: %s. ",
|
165
165
|
missing_env_file_variables_solution: "To add it, connect your script with " \
|
166
166
|
"{{command:%1$s script connect}} ",
|
167
|
+
|
168
|
+
invalid_app_bridge_path_cause: "The script couldn't be pushed because the App Bridge path is incorrect in .shopify-cli.yml.",
|
169
|
+
invalid_app_bridge_path_help: "The %{path_key} needs to be set to a path that starts with {{command:/}}.",
|
167
170
|
},
|
168
171
|
|
169
172
|
create: {
|
@@ -316,6 +316,14 @@ module Script
|
|
316
316
|
),
|
317
317
|
help_suggestion: ShopifyCLI::Context.message("script.error.language_library_for_api_not_found_help"),
|
318
318
|
}
|
319
|
+
when Layers::Infrastructure::Errors::InvalidAppBridgePathError
|
320
|
+
{
|
321
|
+
cause_of_error: ShopifyCLI::Context.message("script.error.invalid_app_bridge_path_cause"),
|
322
|
+
help_suggestion: ShopifyCLI::Context.message(
|
323
|
+
"script.error.invalid_app_bridge_path_help",
|
324
|
+
path_key: e.path_key,
|
325
|
+
),
|
326
|
+
}
|
319
327
|
end
|
320
328
|
end
|
321
329
|
end
|
@@ -12,13 +12,18 @@ module Theme
|
|
12
12
|
parser.on("-t", "--theme=NAME_OR_ID") { |theme| flags[:theme] = theme }
|
13
13
|
parser.on("-l", "--live") { flags[:live] = true }
|
14
14
|
parser.on("-d", "--development") { flags[:development] = true }
|
15
|
+
parser.on("-e", "--editor") { flags[:editor] = true }
|
15
16
|
end
|
16
17
|
|
17
18
|
def call(_args, _name)
|
18
19
|
theme = find_theme(**options.flags)
|
19
20
|
|
20
21
|
@ctx.puts(@ctx.message("theme.open.details", theme.name, theme.preview_url, theme.editor_url))
|
21
|
-
|
22
|
+
if options.flags[:editor]
|
23
|
+
@ctx.open_browser_url!(theme.editor_url)
|
24
|
+
else
|
25
|
+
@ctx.open_browser_url!(theme.preview_url)
|
26
|
+
end
|
22
27
|
end
|
23
28
|
|
24
29
|
def self.help
|
@@ -17,12 +17,16 @@ module Theme
|
|
17
17
|
parser.on("--poll") { flags[:poll] = true }
|
18
18
|
parser.on("--live-reload=MODE") { |mode| flags[:mode] = as_reload_mode(mode) }
|
19
19
|
parser.on("--theme-editor-sync") { flags[:editor_sync] = true }
|
20
|
+
parser.on("-t", "--theme=NAME_OR_ID") { |theme| flags[:theme] = theme }
|
20
21
|
end
|
21
22
|
|
22
23
|
def call(_args, name)
|
24
|
+
valid_authentication_method!
|
25
|
+
|
23
26
|
root = root_value(options, name)
|
24
27
|
flags = options.flags.dup
|
25
28
|
host = flags[:host] || DEFAULT_HTTP_HOST
|
29
|
+
|
26
30
|
ShopifyCLI::Theme::DevServer.start(@ctx, root, host: host, **flags) do |syncer|
|
27
31
|
UI::SyncProgressBar.new(syncer).progress(:upload_theme!, delay_low_priority_files: true)
|
28
32
|
end
|
@@ -38,6 +42,30 @@ module Theme
|
|
38
42
|
def self.help
|
39
43
|
ShopifyCLI::Context.message("theme.serve.help", ShopifyCLI::TOOL_NAME)
|
40
44
|
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def valid_authentication_method!
|
49
|
+
if exchange_token && !storefront_renderer_token
|
50
|
+
ShopifyCLI::Context.abort(error_message, help_message)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def error_message
|
55
|
+
ShopifyCLI::Context.message("theme.serve.auth.error_message", ShopifyCLI::TOOL_NAME)
|
56
|
+
end
|
57
|
+
|
58
|
+
def help_message
|
59
|
+
ShopifyCLI::Context.message("theme.serve.auth.help_message", ShopifyCLI::TOOL_NAME, ShopifyCLI::TOOL_NAME)
|
60
|
+
end
|
61
|
+
|
62
|
+
def exchange_token
|
63
|
+
ShopifyCLI::DB.get(:shopify_exchange_token)
|
64
|
+
end
|
65
|
+
|
66
|
+
def storefront_renderer_token
|
67
|
+
ShopifyCLI::DB.get(:storefront_renderer_production_exchange_token)
|
68
|
+
end
|
41
69
|
end
|
42
70
|
end
|
43
71
|
end
|
@@ -6,7 +6,7 @@ module Theme
|
|
6
6
|
module Forms
|
7
7
|
class Select < ShopifyCLI::Form
|
8
8
|
attr_accessor :theme
|
9
|
-
flag_arguments :root, :title, :exclude_roles, :include_foreign_developments
|
9
|
+
flag_arguments :root, :title, :exclude_roles, :include_foreign_developments, :cmd
|
10
10
|
|
11
11
|
def ask
|
12
12
|
self.theme = CLI::UI::Prompt.ask(title, allow_empty: false) do |handler|
|
@@ -18,6 +18,9 @@ module Theme
|
|
18
18
|
|
19
19
|
handler.option(presenter.to_s(:short)) { theme }
|
20
20
|
end
|
21
|
+
if handler.options.empty? && cmd
|
22
|
+
@ctx.abort(@ctx.message("theme.#{cmd}.no_themes_error"), @ctx.message("theme.#{cmd}.no_themes_resolution"))
|
23
|
+
end
|
21
24
|
end
|
22
25
|
end
|
23
26
|
|
@@ -8,6 +8,11 @@ module Theme
|
|
8
8
|
Usage: {{command:%1$s theme [ %2$s ]}}
|
9
9
|
HELP
|
10
10
|
ensure_user_error: "You are not authorized to edit themes on %s.",
|
11
|
+
unauthorized_error: <<~EOD,
|
12
|
+
You can't use Shopify CLI with development stores if you only have Partner staff member access. If you want to use Shopify CLI to work on a development store, then you should be the store owner or create a staff account on the store.
|
13
|
+
|
14
|
+
If you're the store owner, then you need to log in to the store directly using the store URL at least once (for example, using %s.myshopify.com/admin) before you log in using Shopify CLI. Logging in to the Shopify admin directly connects the development store with your Shopify login.
|
15
|
+
EOD
|
11
16
|
ensure_user_try_this: <<~ENSURE_USER,
|
12
17
|
Check if your user is activated, has permission to edit themes at the store, and try to re-login.
|
13
18
|
ENSURE_USER
|
@@ -37,6 +42,8 @@ module Theme
|
|
37
42
|
HELP
|
38
43
|
done: "Your theme is now live at %s",
|
39
44
|
not_found: "Theme #%s does not exist",
|
45
|
+
no_themes_error: "You don't have any theme to be published.",
|
46
|
+
no_themes_resolution: "Try to create an unpublished theme with {{command:theme push -u -t <theme_name>}}.",
|
40
47
|
select: "Select theme to push to",
|
41
48
|
confirm: "Are you sure you want to make %s the new live theme on %s?",
|
42
49
|
},
|
@@ -96,6 +103,7 @@ module Theme
|
|
96
103
|
name: "Theme name",
|
97
104
|
},
|
98
105
|
serve: {
|
106
|
+
theme_not_found: "Theme \"%s\" doesn't exist",
|
99
107
|
help: <<~HELP,
|
100
108
|
Uploads the current theme as a development theme to the connected store, then prints theme editor and preview URLs to your terminal. While running, changes will push to the store in real time.
|
101
109
|
|
@@ -116,6 +124,14 @@ module Theme
|
|
116
124
|
viewing_theme: "Viewing theme…",
|
117
125
|
syncing_theme: "Syncing theme #%s on %s",
|
118
126
|
open_fail: "Couldn't open the theme",
|
127
|
+
auth: {
|
128
|
+
error_message: <<~ERROR_MESSAGE,
|
129
|
+
It looks like you are using credentials that do not work with {{command:%s theme serve}}.
|
130
|
+
ERROR_MESSAGE
|
131
|
+
help_message: <<~HELP_MESSAGE,
|
132
|
+
Run {{command:%s logout}} and {{command:%s login --password "" --store STORE}} to force the authentication thought your browser.
|
133
|
+
HELP_MESSAGE
|
134
|
+
},
|
119
135
|
operation: {
|
120
136
|
status: {
|
121
137
|
error: "ERROR",
|
@@ -126,14 +142,14 @@ module Theme
|
|
126
142
|
syncer: {
|
127
143
|
forms: {
|
128
144
|
apply_to_all: {
|
129
|
-
title: "Would like apply this to all the other %s files?",
|
145
|
+
title: "Would you like to apply this to all the other %s files?",
|
130
146
|
yes: "Yes",
|
131
147
|
no: "No",
|
132
148
|
},
|
133
149
|
update_strategy: {
|
134
150
|
title_context: <<~TITLE,
|
135
151
|
|
136
|
-
The local file {{command:%s}} is different from the remote version in the development theme.
|
152
|
+
The local file {{command:%s}} is different from the remote version in the development theme.
|
137
153
|
TITLE
|
138
154
|
title_question: "What would you like to do?",
|
139
155
|
keep_remote: "Keep the remote version",
|
@@ -141,10 +157,21 @@ module Theme
|
|
141
157
|
union_merge: "Merge files (it may break the local file)",
|
142
158
|
exit: "Exit",
|
143
159
|
},
|
160
|
+
update_remote_deleted_strategy: {
|
161
|
+
title_context: <<~TITLE,
|
162
|
+
|
163
|
+
The local file {{command:%s}} doesn’t exist in the remote version of the development theme.
|
164
|
+
TITLE
|
165
|
+
title_question: "What would you like to do?",
|
166
|
+
keep_remote: "Keep the remote version (and remove it locally)",
|
167
|
+
keep_local: "Keep the local version (and restore it remotely)",
|
168
|
+
union_merge: "Merge files (it may break the local file)",
|
169
|
+
exit: "Exit",
|
170
|
+
},
|
144
171
|
delete_strategy: {
|
145
172
|
title_context: <<~TITLE,
|
146
173
|
|
147
|
-
The local file {{command:%s}} has been recently removed, but it's present on your remote development theme.
|
174
|
+
The local file {{command:%s}} has been recently removed, but it's present on your remote development theme.
|
148
175
|
TITLE
|
149
176
|
title_question: "What would you like to do?",
|
150
177
|
delete: "Delete permanently",
|
@@ -209,6 +236,8 @@ module Theme
|
|
209
236
|
HELP
|
210
237
|
select: "Select theme to delete",
|
211
238
|
done: "%s theme(s) deleted",
|
239
|
+
no_themes_error: "You don't have any theme to be deleted.",
|
240
|
+
no_themes_resolution: "Try to create an unpublished theme with {{command:theme push -u -t <theme_name>}}.",
|
212
241
|
not_found: "{{x}} Theme #%s does not exist",
|
213
242
|
live: "{{x}} Theme #%s is your live theme. You can't delete it.",
|
214
243
|
confirm: "Are you sure you want to delete %s on %s?",
|
@@ -280,6 +309,7 @@ module Theme
|
|
280
309
|
{{command:-t, --theme=NAME_OR_ID}} Theme ID or name of your theme.
|
281
310
|
{{command:-l, --live}} Open your live theme.
|
282
311
|
{{command:-d, --development}} Open your development theme.
|
312
|
+
{{command:-e, --editor}} Open the editor to the specified/selected theme.
|
283
313
|
HELP
|
284
314
|
},
|
285
315
|
list: {
|
@@ -26,8 +26,8 @@ module ShopifyCLI
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
|
30
|
-
if
|
29
|
+
password = options.flags[:password] || @ctx.getenv("SHOPIFY_PASSWORD")
|
30
|
+
if !password.nil? && !password.empty?
|
31
31
|
ShopifyCLI::DB.set(shopify_exchange_token: password)
|
32
32
|
else
|
33
33
|
IdentityAuth.new(ctx: @ctx).authenticate(spinner: true)
|
data/lib/shopify_cli/context.rb
CHANGED
@@ -630,7 +630,7 @@ module ShopifyCLI
|
|
630
630
|
end
|
631
631
|
end
|
632
632
|
latest_version = ShopifyCLI::Config.get(VERSION_CHECK_SECTION, LATEST_VERSION_FIELD, default: ShopifyCLI::VERSION)
|
633
|
-
latest_version
|
633
|
+
latest_version if ::Semantic::Version.new(latest_version) > ::Semantic::Version.new(ShopifyCLI::VERSION)
|
634
634
|
end
|
635
635
|
|
636
636
|
# Returns file extension depending on OS
|
@@ -6,7 +6,7 @@ require "rbconfig"
|
|
6
6
|
module ShopifyCLI
|
7
7
|
module Core
|
8
8
|
module Monorail
|
9
|
-
ENDPOINT_URI = URI.parse("https://monorail-edge.
|
9
|
+
ENDPOINT_URI = URI.parse("https://monorail-edge.shopifysvc.com/v1/produce")
|
10
10
|
INVOCATIONS_SCHEMA = "app_cli_command/5.0"
|
11
11
|
|
12
12
|
# Extra hash of data that will be sent in the payload
|
data/lib/shopify_cli/git.rb
CHANGED
@@ -67,9 +67,14 @@ module ShopifyCLI
|
|
67
67
|
if Dir.exist?(dest)
|
68
68
|
ctx.abort(ctx.message("core.git.error.directory_exists"))
|
69
69
|
else
|
70
|
+
repo, branch = repository.split("#")
|
70
71
|
success_message = ctx.message("core.git.cloned", dest)
|
71
|
-
CLI::UI::Frame.open(ctx.message("core.git.cloning",
|
72
|
-
|
72
|
+
CLI::UI::Frame.open(ctx.message("core.git.cloning", repo, dest), success_text: success_message) do
|
73
|
+
if branch
|
74
|
+
clone_progress("clone", "--single-branch", "--branch", branch, repo, dest, ctx: ctx)
|
75
|
+
else
|
76
|
+
clone_progress("clone", "--single-branch", repo, dest, ctx: ctx)
|
77
|
+
end
|
73
78
|
end
|
74
79
|
end
|
75
80
|
end
|
data/lib/shopify_cli/heroku.rb
CHANGED
@@ -4,6 +4,7 @@ module ShopifyCLI
|
|
4
4
|
linux: "https://cli-assets.heroku.com/heroku-linux-x64.tar.gz",
|
5
5
|
mac: "https://cli-assets.heroku.com/heroku-darwin-x64.tar.gz",
|
6
6
|
windows: "https://cli-assets.heroku.com/heroku-x64.exe",
|
7
|
+
mac_m1: "https://cli-assets.heroku.com/heroku-darwin-x64.tar.gz",
|
7
8
|
}
|
8
9
|
|
9
10
|
def initialize(ctx)
|
@@ -97,15 +98,16 @@ module ShopifyCLI
|
|
97
98
|
if File.exist?(local_path)
|
98
99
|
local_path
|
99
100
|
elsif @ctx.windows?
|
100
|
-
# Check if Heroku exists in the Windows registry and run it from there
|
101
|
-
require "win32/registry"
|
102
101
|
begin
|
102
|
+
# Check if Heroku exists in the Windows registry and run it from there
|
103
|
+
require "win32/registry"
|
104
|
+
|
103
105
|
windows_path = Win32::Registry::HKEY_CURRENT_USER.open('SOFTWARE\heroku') do |reg|
|
104
106
|
reg[""] # This reads the 'Default' registry key
|
105
107
|
end
|
106
108
|
|
107
109
|
File.join(windows_path, "bin", "heroku").to_s
|
108
|
-
rescue
|
110
|
+
rescue StandardError, LoadError
|
109
111
|
"heroku"
|
110
112
|
end
|
111
113
|
else
|
data/lib/shopify_cli/release.rb
CHANGED
@@ -8,7 +8,6 @@ module ShopifyCLI
|
|
8
8
|
class Release
|
9
9
|
def initialize(new_version, github_access_token)
|
10
10
|
@new_version = new_version
|
11
|
-
@changelog = ShopifyCLI::Changelog.new
|
12
11
|
@github = Octokit::Client.new(access_token: github_access_token)
|
13
12
|
end
|
14
13
|
|
@@ -32,7 +31,7 @@ module ShopifyCLI
|
|
32
31
|
|
33
32
|
private
|
34
33
|
|
35
|
-
attr_reader :new_version, :
|
34
|
+
attr_reader :new_version, :github
|
36
35
|
|
37
36
|
def ensure_updated_main
|
38
37
|
# We can't be sure what is the correct action to take if changes have been
|
@@ -190,5 +189,9 @@ module ShopifyCLI
|
|
190
189
|
def system_or_fail(command, action)
|
191
190
|
raise "Failed to #{action}!" unless system(command)
|
192
191
|
end
|
192
|
+
|
193
|
+
def changelog
|
194
|
+
@changelog ||= ShopifyCLI::Changelog.new
|
195
|
+
end
|
193
196
|
end
|
194
197
|
end
|
@@ -117,7 +117,7 @@ module ShopifyCLI
|
|
117
117
|
end
|
118
118
|
|
119
119
|
def build(name)
|
120
|
-
ShopifyCLI::Git.clone("https://github.com/Shopify/shopify-app-node.git", name)
|
120
|
+
ShopifyCLI::Git.clone("https://github.com/Shopify/shopify-app-template-node.git#cli_two", name)
|
121
121
|
|
122
122
|
context.root = File.join(context.root, name)
|
123
123
|
|
@@ -74,7 +74,7 @@ module ShopifyCLI
|
|
74
74
|
end
|
75
75
|
|
76
76
|
def build(form)
|
77
|
-
ShopifyCLI::Git.clone("https://github.com/Shopify/shopify-app-php.git", form.name)
|
77
|
+
ShopifyCLI::Git.clone("https://github.com/Shopify/shopify-app-template-php.git#cli_two", form.name)
|
78
78
|
|
79
79
|
context.root = File.join(context.root, form.name)
|
80
80
|
context.chdir(context.root)
|
@@ -14,13 +14,12 @@ module ShopifyCLI
|
|
14
14
|
|
15
15
|
files.each do |file|
|
16
16
|
section_hash(file).each do |key, value|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
next if !name || !type
|
17
|
+
next unless key
|
18
|
+
next unless value.is_a?(Hash)
|
19
|
+
next unless (type = value&.dig("type"))
|
21
20
|
|
22
21
|
index[type] = [] unless index[type]
|
23
|
-
index[type] <<
|
22
|
+
index[type] << key
|
24
23
|
end
|
25
24
|
end
|
26
25
|
|
@@ -42,7 +41,7 @@ module ShopifyCLI
|
|
42
41
|
end
|
43
42
|
|
44
43
|
def files
|
45
|
-
@theme.json_files
|
44
|
+
@theme.json_files.filter(&:template?)
|
46
45
|
end
|
47
46
|
end
|
48
47
|
end
|
@@ -14,7 +14,8 @@ module ShopifyCLI
|
|
14
14
|
@theme = theme
|
15
15
|
@syncer = syncer
|
16
16
|
@ignore_filter = ignore_filter
|
17
|
-
@listener = Listen.to(@theme.root, force_polling: poll
|
17
|
+
@listener = Listen.to(@theme.root, force_polling: poll,
|
18
|
+
ignore: @ignore_filter&.regexes) do |modified, added, removed|
|
18
19
|
changed
|
19
20
|
notify_observers(modified, added, removed)
|
20
21
|
end
|
@@ -27,12 +27,13 @@ module ShopifyCLI
|
|
27
27
|
class << self
|
28
28
|
attr_accessor :ctx
|
29
29
|
|
30
|
-
def start(ctx, root, host: "127.0.0.1", port: 9292, poll: false, editor_sync: false,
|
30
|
+
def start(ctx, root, host: "127.0.0.1", theme: nil, port: 9292, poll: false, editor_sync: false,
|
31
|
+
mode: ReloadMode.default)
|
31
32
|
@ctx = ctx
|
32
|
-
theme =
|
33
|
+
theme = find_theme(root, theme)
|
33
34
|
ignore_filter = IgnoreFilter.from_path(root)
|
34
35
|
@syncer = Syncer.new(ctx, theme: theme, ignore_filter: ignore_filter, overwrite_json: !editor_sync)
|
35
|
-
watcher = Watcher.new(ctx, theme: theme, syncer: @syncer, poll: poll)
|
36
|
+
watcher = Watcher.new(ctx, theme: theme, ignore_filter: ignore_filter, syncer: @syncer, poll: poll)
|
36
37
|
remote_watcher = RemoteWatcher.to(theme: theme, syncer: @syncer)
|
37
38
|
|
38
39
|
# Setup the middleware stack. Mimics Rack::Builder / config.ru, but in reverse order
|
@@ -108,6 +109,22 @@ module ShopifyCLI
|
|
108
109
|
@syncer.shutdown
|
109
110
|
WebServer.shutdown
|
110
111
|
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def find_theme(root, identifier)
|
116
|
+
return theme_by_identifier(root, identifier) if identifier
|
117
|
+
DevelopmentTheme.find_or_create!(@ctx, root: root)
|
118
|
+
end
|
119
|
+
|
120
|
+
def theme_by_identifier(root, identifier)
|
121
|
+
theme = ShopifyCLI::Theme::Theme.find_by_identifier(@ctx, root: root, identifier: identifier)
|
122
|
+
theme || not_found_error(identifier)
|
123
|
+
end
|
124
|
+
|
125
|
+
def not_found_error(identifier)
|
126
|
+
@ctx.abort(@ctx.message("theme.serve.theme_not_found", identifier))
|
127
|
+
end
|
111
128
|
end
|
112
129
|
end
|
113
130
|
end
|
@@ -79,13 +79,23 @@ module ShopifyCLI
|
|
79
79
|
|
80
80
|
theme_name = "Development ()"
|
81
81
|
hostname_character_limit = API_NAME_LIMIT - theme_name.length - hash.length - 1
|
82
|
-
identifier = "#{hash}-#{hostname[0, hostname_character_limit]}"
|
82
|
+
identifier = encode_identifier("#{hash}-#{hostname[0, hostname_character_limit]}")
|
83
83
|
theme_name = "Development (#{identifier})"
|
84
84
|
|
85
85
|
ShopifyCLI::DB.set(development_theme_name: theme_name)
|
86
86
|
|
87
87
|
theme_name
|
88
88
|
end
|
89
|
+
|
90
|
+
##
|
91
|
+
# In some cases, the identifier string encoding may be obfuscated by the hostname,
|
92
|
+
# which may be an ASCII string.
|
93
|
+
#
|
94
|
+
# This method ensures the result identifier is a UTF-8 valid string.
|
95
|
+
#
|
96
|
+
def encode_identifier(identifier)
|
97
|
+
identifier.encode(Encoding::UTF_8, invalid: :replace, undef: :replace, replace: "-")
|
98
|
+
end
|
89
99
|
end
|
90
100
|
end
|
91
101
|
end
|
@@ -30,6 +30,15 @@ module ShopifyCLI
|
|
30
30
|
else
|
31
31
|
path.write(content, 0, mode: "wb")
|
32
32
|
end
|
33
|
+
rescue Encoding::UndefinedConversionError
|
34
|
+
##
|
35
|
+
# The CLI tries to write the file and normalize EOL characters to avoid
|
36
|
+
# errors on Windows when files are shared across different operational systems.
|
37
|
+
#
|
38
|
+
# The CLI fallbacks any error during the conversion by writing the file
|
39
|
+
# in binary mode when the normalization fails (e.g., ASCII files), so no data is lost.
|
40
|
+
#
|
41
|
+
path.write(content, 0, mode: "wb")
|
33
42
|
end
|
34
43
|
|
35
44
|
def delete
|
@@ -7,7 +7,7 @@ module ShopifyCLI
|
|
7
7
|
class Syncer
|
8
8
|
module Forms
|
9
9
|
class SelectUpdateStrategy < BaseStrategyForm
|
10
|
-
flag_arguments :file
|
10
|
+
flag_arguments :file, :exists_remotely
|
11
11
|
|
12
12
|
def strategies
|
13
13
|
%i[
|
@@ -19,7 +19,7 @@ module ShopifyCLI
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def prefix
|
22
|
-
"theme.serve.syncer.forms
|
22
|
+
"theme.serve.syncer.forms.#{exists_remotely ? "update_strategy" : "update_remote_deleted_strategy"}"
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
@@ -53,8 +53,10 @@ module ShopifyCLI
|
|
53
53
|
# * when an asset operation cannot be performed:
|
54
54
|
# - <APIRequestForbiddenError: 403 {"message":"templates/gift_card.liquid could not be deleted"}>
|
55
55
|
#
|
56
|
-
if empty_response?(error)
|
56
|
+
if empty_response?(error)
|
57
57
|
return permission_error
|
58
|
+
elsif unauthorized_response?(error)
|
59
|
+
raise ShopifyCLI::Abort, @ctx.message("theme.unauthorized_error", @shop)
|
58
60
|
end
|
59
61
|
|
60
62
|
raise error
|
data/lib/shopify_cli/version.rb
CHANGED