shopify-cli 2.12.0 → 2.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/shopify.yml +2 -1
- data/.rubocop.yml +1 -1
- data/.ruby-version +1 -1
- data/CHANGELOG.md +10 -0
- data/Gemfile.lock +14 -14
- data/bin/shopify +4 -4
- data/dev.yml +1 -1
- data/ext/javy/hashes/javy-arm-macos-v0.2.0.gz.sha256 +1 -0
- data/ext/javy/hashes/javy-x86_64-linux-v0.2.0.gz.sha256 +1 -0
- data/ext/javy/hashes/javy-x86_64-macos-v0.2.0.gz.sha256 +1 -0
- data/ext/javy/hashes/javy-x86_64-windows-v0.2.0.gz.sha256 +1 -0
- data/ext/javy/version +1 -1
- data/lib/project_types/extension/features/argo_setup_steps.rb +4 -6
- data/lib/project_types/extension/tasks/configure_features.rb +15 -2
- data/lib/project_types/extension/tasks/convert_server_config.rb +2 -1
- data/lib/project_types/script/commands/create.rb +4 -4
- data/lib/project_types/script/errors.rb +1 -1
- data/lib/project_types/script/forms/create.rb +7 -7
- data/lib/project_types/script/layers/application/build_script.rb +22 -24
- data/lib/project_types/script/layers/application/create_script.rb +9 -10
- data/lib/project_types/script/layers/application/project_dependencies.rb +12 -14
- data/lib/project_types/script/layers/application/push_script.rb +2 -0
- data/lib/project_types/script/layers/domain/errors.rb +3 -3
- data/lib/project_types/script/layers/domain/push_package.rb +6 -0
- data/lib/project_types/script/layers/domain/script_config.rb +2 -4
- data/lib/project_types/script/layers/domain/script_project.rb +3 -2
- data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb +19 -4
- data/lib/project_types/script/layers/infrastructure/languages/project_creator.rb +0 -15
- data/lib/project_types/script/layers/infrastructure/languages/typescript_project_creator.rb +19 -4
- data/lib/project_types/script/layers/infrastructure/languages/wasm_project_creator.rb +0 -3
- data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +4 -0
- data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +13 -25
- data/lib/project_types/script/layers/infrastructure/script_service.rb +4 -2
- data/lib/project_types/script/messages/messages.rb +7 -7
- data/lib/project_types/script/ui/error_handler.rb +4 -4
- data/lib/project_types/script/ui/strict_spinner.rb +4 -6
- data/lib/project_types/theme/cli.rb +2 -0
- data/lib/project_types/theme/commands/common/root_helper.rb +11 -5
- data/lib/project_types/theme/commands/list.rb +34 -0
- data/lib/project_types/theme/commands/open.rb +65 -0
- data/lib/project_types/theme/commands/pull.rb +2 -2
- data/lib/project_types/theme/commands/push.rb +2 -2
- data/lib/project_types/theme/forms/select.rb +11 -39
- data/lib/project_types/theme/messages/messages.rb +31 -2
- data/lib/project_types/theme/presenters/theme_presenter.rb +48 -0
- data/lib/project_types/theme/presenters/themes_presenter.rb +32 -0
- data/lib/shopify_cli/api.rb +1 -1
- data/lib/shopify_cli/constants.rb +2 -2
- data/lib/shopify_cli/context.rb +11 -13
- data/lib/shopify_cli/services/app/create/rails_service.rb +1 -1
- data/lib/shopify_cli/theme/syncer.rb +7 -7
- data/lib/shopify_cli/version.rb +1 -1
- data/shopify-dev +9 -11
- metadata +10 -2
@@ -5,10 +5,6 @@ module Script
|
|
5
5
|
module Infrastructure
|
6
6
|
module Languages
|
7
7
|
class TypeScriptProjectCreator < ProjectCreator
|
8
|
-
def self.config_file
|
9
|
-
"package.json"
|
10
|
-
end
|
11
|
-
|
12
8
|
def setup_dependencies
|
13
9
|
task_runner = Infrastructure::Languages::TypeScriptTaskRunner.new(ctx)
|
14
10
|
task_runner.set_npm_config
|
@@ -22,6 +18,25 @@ module Script
|
|
22
18
|
if ctx.file_exist?("package-lock.json")
|
23
19
|
ctx.rm("package-lock.json")
|
24
20
|
end
|
21
|
+
|
22
|
+
update_package_json_name
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def update_package_json_name
|
28
|
+
file_content = ctx.read("package.json")
|
29
|
+
hash = file_content_to_hash(file_content)
|
30
|
+
hash["name"] = project_name
|
31
|
+
ctx.write("package.json", hash_to_file_content(hash))
|
32
|
+
end
|
33
|
+
|
34
|
+
def file_content_to_hash(content)
|
35
|
+
JSON.parse(content)
|
36
|
+
end
|
37
|
+
|
38
|
+
def hash_to_file_content(hash)
|
39
|
+
JSON.pretty_generate(hash)
|
25
40
|
end
|
26
41
|
end
|
27
42
|
end
|
@@ -15,6 +15,8 @@ module Script
|
|
15
15
|
id: build_file_path,
|
16
16
|
uuid: script_project.uuid,
|
17
17
|
extension_point_type: script_project.extension_point_type,
|
18
|
+
title: script_project.title,
|
19
|
+
description: script_project.description,
|
18
20
|
script_content: script_content,
|
19
21
|
metadata: metadata,
|
20
22
|
script_config: script_project.script_config,
|
@@ -31,6 +33,8 @@ module Script
|
|
31
33
|
id: build_file_path,
|
32
34
|
uuid: script_project.uuid,
|
33
35
|
extension_point_type: script_project.extension_point_type,
|
36
|
+
title: script_project.title,
|
37
|
+
description: script_project.description,
|
34
38
|
script_content: script_content,
|
35
39
|
metadata: metadata,
|
36
40
|
script_config: script_project.script_config,
|
@@ -27,7 +27,7 @@ module Script
|
|
27
27
|
change_directory(directory: initial_directory)
|
28
28
|
end
|
29
29
|
|
30
|
-
def create(
|
30
|
+
def create(title:, extension_point_type:, language:)
|
31
31
|
validate_metadata!(extension_point_type, language)
|
32
32
|
|
33
33
|
ShopifyCLI::Project.write(
|
@@ -35,7 +35,8 @@ module Script
|
|
35
35
|
project_type: :script,
|
36
36
|
organization_id: nil,
|
37
37
|
extension_point_type: extension_point_type,
|
38
|
-
|
38
|
+
title: title,
|
39
|
+
description: nil,
|
39
40
|
language: language
|
40
41
|
)
|
41
42
|
|
@@ -48,7 +49,8 @@ module Script
|
|
48
49
|
Domain::ScriptProject.new(
|
49
50
|
id: project.directory,
|
50
51
|
env: project.env,
|
51
|
-
|
52
|
+
title: title,
|
53
|
+
description: description,
|
52
54
|
extension_point_type: extension_point_type,
|
53
55
|
language: language,
|
54
56
|
script_config: script_config_repository.get!,
|
@@ -79,11 +81,6 @@ module Script
|
|
79
81
|
build_script_project
|
80
82
|
end
|
81
83
|
|
82
|
-
def update_script_config(title:)
|
83
|
-
script_config = script_config_repository.update!(title: title)
|
84
|
-
build_script_project(script_config: script_config)
|
85
|
-
end
|
86
|
-
|
87
84
|
private
|
88
85
|
|
89
86
|
def build_script_project(
|
@@ -92,7 +89,8 @@ module Script
|
|
92
89
|
Domain::ScriptProject.new(
|
93
90
|
id: ctx.root,
|
94
91
|
env: project.env,
|
95
|
-
|
92
|
+
title: title,
|
93
|
+
description: description,
|
96
94
|
extension_point_type: extension_point_type,
|
97
95
|
language: language,
|
98
96
|
script_config: script_config,
|
@@ -111,8 +109,12 @@ module Script
|
|
111
109
|
project_config_value!("extension_point_type")
|
112
110
|
end
|
113
111
|
|
114
|
-
def
|
115
|
-
project_config_value!("
|
112
|
+
def title
|
113
|
+
project_config_value!("title")
|
114
|
+
end
|
115
|
+
|
116
|
+
def description
|
117
|
+
project_config_value("description")
|
116
118
|
end
|
117
119
|
|
118
120
|
def language
|
@@ -181,26 +183,12 @@ module Script
|
|
181
183
|
from_h(hash)
|
182
184
|
end
|
183
185
|
|
184
|
-
def update!(title:)
|
185
|
-
hash = get!.content
|
186
|
-
update_hash(hash: hash, title: title)
|
187
|
-
|
188
|
-
ctx.write(filename, hash_to_file_content(hash))
|
189
|
-
|
190
|
-
from_h(hash)
|
191
|
-
end
|
192
|
-
|
193
186
|
def filename
|
194
187
|
raise NotImplementedError
|
195
188
|
end
|
196
189
|
|
197
190
|
private
|
198
191
|
|
199
|
-
def update_hash(hash:, title:)
|
200
|
-
hash["version"] ||= "2"
|
201
|
-
hash["title"] = title
|
202
|
-
end
|
203
|
-
|
204
192
|
def from_h(hash)
|
205
193
|
Domain::ScriptConfig.new(content: hash, filename: filename)
|
206
194
|
end
|
@@ -15,6 +15,8 @@ module Script
|
|
15
15
|
def set_app_script(
|
16
16
|
uuid:,
|
17
17
|
extension_point_type:,
|
18
|
+
title:,
|
19
|
+
description:,
|
18
20
|
force: false,
|
19
21
|
metadata:,
|
20
22
|
script_config:,
|
@@ -26,8 +28,8 @@ module Script
|
|
26
28
|
variables = {
|
27
29
|
uuid: uuid,
|
28
30
|
extensionPointName: extension_point_type.upcase,
|
29
|
-
title:
|
30
|
-
description:
|
31
|
+
title: title,
|
32
|
+
description: description,
|
31
33
|
force: force,
|
32
34
|
schemaMajorVersion: metadata.schema_major_version.to_s, # API expects string value
|
33
35
|
schemaMinorVersion: metadata.schema_minor_version.to_s, # API expects string value
|
@@ -24,11 +24,11 @@ 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 or title.",
|
28
28
|
invalid_context_help: "Add these values.",
|
29
29
|
|
30
|
-
|
31
|
-
|
30
|
+
invalid_script_title_cause: "Script title contains unsupported characters.",
|
31
|
+
invalid_script_title_help: "Use only numbers, letters, hyphens, or underscores.",
|
32
32
|
|
33
33
|
no_existing_apps_cause: "Your script can't be pushed to an app because your Partner account "\
|
34
34
|
"doesn't have any apps.",
|
@@ -37,8 +37,8 @@ module Script
|
|
37
37
|
no_existing_orgs_cause: "Your account doesn't belong to a Partner Organization.",
|
38
38
|
no_existing_orgs_help: "Visit https://partners.shopify.com/ to create an account.",
|
39
39
|
|
40
|
-
project_exists_cause: "A directory with this same
|
41
|
-
project_exists_help: "Choose a different
|
40
|
+
project_exists_cause: "A directory with this same title already exists.",
|
41
|
+
project_exists_help: "Choose a different title for your script.",
|
42
42
|
|
43
43
|
invalid_extension_cause: "The name of the Script API is incorrect: %s.",
|
44
44
|
invalid_extension_help: "Choose a supported API: %s.",
|
@@ -168,7 +168,7 @@ module Script
|
|
168
168
|
{{command:%1$s script create}}: Creates a script project.
|
169
169
|
Usage: {{command:%1$s script create}}
|
170
170
|
Options:
|
171
|
-
{{command:--
|
171
|
+
{{command:--title=TITLE}} Script project title.
|
172
172
|
{{command:--api=TYPE}} Script API name. Supported values: %2$s.
|
173
173
|
{{command:--language=LANGUAGE}} Programming language. Defaults to wasm. Supported values: %3$s.
|
174
174
|
HELP
|
@@ -235,7 +235,7 @@ module Script
|
|
235
235
|
forms: {
|
236
236
|
create: {
|
237
237
|
select_extension_point: "Which Script API do you want to use?",
|
238
|
-
|
238
|
+
script_title: "What do you want to title your script?",
|
239
239
|
},
|
240
240
|
},
|
241
241
|
|
@@ -59,10 +59,10 @@ module Script
|
|
59
59
|
Script::Layers::Application::ExtensionPoints.languages(type: e.extension_point_type).join(", ")
|
60
60
|
),
|
61
61
|
}
|
62
|
-
when Errors::
|
62
|
+
when Errors::InvalidScriptTitleError
|
63
63
|
{
|
64
|
-
cause_of_error: ShopifyCLI::Context.message("script.error.
|
65
|
-
help_suggestion: ShopifyCLI::Context.message("script.error.
|
64
|
+
cause_of_error: ShopifyCLI::Context.message("script.error.invalid_script_title_cause"),
|
65
|
+
help_suggestion: ShopifyCLI::Context.message("script.error.invalid_script_title_help"),
|
66
66
|
}
|
67
67
|
when Errors::NoExistingAppsError
|
68
68
|
{
|
@@ -96,7 +96,7 @@ module Script
|
|
96
96
|
{
|
97
97
|
cause_of_error: ShopifyCLI::Context.message(
|
98
98
|
"script.error.script_not_found_cause",
|
99
|
-
e.
|
99
|
+
e.title,
|
100
100
|
e.extension_point_type
|
101
101
|
),
|
102
102
|
}
|
@@ -8,12 +8,10 @@ module Script
|
|
8
8
|
def self.spin(title, auto_debrief: false)
|
9
9
|
exception = nil
|
10
10
|
CLI::UI::Spinner.spin(title, auto_debrief: auto_debrief) do |*args|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
CLI::UI::Spinner::TASK_FAILED
|
16
|
-
end
|
11
|
+
yield(*args)
|
12
|
+
rescue StandardError => e
|
13
|
+
exception = e
|
14
|
+
CLI::UI::Spinner::TASK_FAILED
|
17
15
|
end
|
18
16
|
raise exception if exception
|
19
17
|
end
|
@@ -14,6 +14,8 @@ module Theme
|
|
14
14
|
subcommand :Check, "check", Project.project_filepath("commands/check")
|
15
15
|
subcommand :Publish, "publish", Project.project_filepath("commands/publish")
|
16
16
|
subcommand :Package, "package", Project.project_filepath("commands/package")
|
17
|
+
subcommand :Open, "open", Project.project_filepath("commands/open")
|
18
|
+
subcommand :List, "list", Project.project_filepath("commands/list")
|
17
19
|
subcommand :LanguageServer, "language-server", Project.project_filepath("commands/language_server")
|
18
20
|
end
|
19
21
|
ShopifyCLI::Commands.register("Theme::Command", "theme")
|
@@ -15,15 +15,16 @@ module Theme
|
|
15
15
|
|
16
16
|
while next_index < argv.size
|
17
17
|
element = argv[next_index]
|
18
|
-
|
18
|
+
key, value = key_value_tuple(element)
|
19
|
+
option = option_by_key[key]
|
19
20
|
|
20
21
|
return element if option.nil?
|
21
22
|
|
22
23
|
# Skip the option argument
|
23
|
-
next_index += 1
|
24
|
+
next_index += 1 if !option.arg.nil? && !value
|
24
25
|
|
25
26
|
# PATTERN arguments take precedence over the `root`
|
26
|
-
if option.arg =~ /PATTERN/
|
27
|
+
if option.arg =~ /PATTERN/ && !value
|
27
28
|
next_index += 1 while option_argument?(argv, next_index, option_by_key)
|
28
29
|
next
|
29
30
|
end
|
@@ -37,7 +38,7 @@ module Theme
|
|
37
38
|
private
|
38
39
|
|
39
40
|
def default_argv(options)
|
40
|
-
options.parser.default_argv
|
41
|
+
options.parser.default_argv.compact
|
41
42
|
end
|
42
43
|
|
43
44
|
def options_map(options)
|
@@ -57,7 +58,12 @@ module Theme
|
|
57
58
|
return false unless next_index < argv.size
|
58
59
|
|
59
60
|
element = argv[next_index]
|
60
|
-
|
61
|
+
key, _value = key_value_tuple(element)
|
62
|
+
option_by_key[key].nil?
|
63
|
+
end
|
64
|
+
|
65
|
+
def key_value_tuple(element)
|
66
|
+
element.split("=")
|
61
67
|
end
|
62
68
|
end
|
63
69
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "shopify_cli/theme/theme"
|
4
|
+
require "project_types/theme/presenters/themes_presenter"
|
5
|
+
|
6
|
+
module Theme
|
7
|
+
class Command
|
8
|
+
class List < ShopifyCLI::Command::SubCommand
|
9
|
+
recommend_default_ruby_range
|
10
|
+
|
11
|
+
def call(_args, _name)
|
12
|
+
@ctx.puts(@ctx.message("theme.list.title", shop))
|
13
|
+
|
14
|
+
themes_presenter.all.each do |theme|
|
15
|
+
@ctx.puts(" #{theme}")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.help
|
20
|
+
@ctx.message("theme.list.help", ShopifyCLI::TOOL_NAME, ShopifyCLI::TOOL_NAME)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def themes_presenter
|
26
|
+
Theme::Presenters::ThemesPresenter.new(@ctx, nil)
|
27
|
+
end
|
28
|
+
|
29
|
+
def shop
|
30
|
+
ShopifyCLI::AdminAPI.get_shop_or_abort(@ctx)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "shopify_cli/theme/theme"
|
4
|
+
require "shopify_cli/theme/development_theme"
|
5
|
+
|
6
|
+
module Theme
|
7
|
+
class Command
|
8
|
+
class Open < ShopifyCLI::Command::SubCommand
|
9
|
+
recommend_default_ruby_range
|
10
|
+
|
11
|
+
options do |parser, flags|
|
12
|
+
parser.on("-t", "--theme=NAME_OR_ID") { |theme| flags[:theme] = theme }
|
13
|
+
parser.on("-l", "--live") { flags[:live] = true }
|
14
|
+
parser.on("-d", "--development") { flags[:development] = true }
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(_args, _name)
|
18
|
+
theme = find_theme(**options.flags)
|
19
|
+
|
20
|
+
@ctx.puts(@ctx.message("theme.open.details", theme.name, theme.editor_url))
|
21
|
+
@ctx.open_url!(theme.preview_url)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.help
|
25
|
+
ShopifyCLI::Context.message("theme.open.help", ShopifyCLI::TOOL_NAME, ShopifyCLI::TOOL_NAME)
|
26
|
+
end
|
27
|
+
|
28
|
+
def find_theme(theme: nil, live: nil, development: nil, **_args)
|
29
|
+
return theme_by_identifier(theme) if theme
|
30
|
+
return live_theme if live
|
31
|
+
return development_theme if development
|
32
|
+
|
33
|
+
select_theme
|
34
|
+
end
|
35
|
+
|
36
|
+
def theme_by_identifier(identifier)
|
37
|
+
theme = ShopifyCLI::Theme::Theme.find_by_identifier(@ctx, identifier: identifier)
|
38
|
+
theme || not_found_error(identifier)
|
39
|
+
end
|
40
|
+
|
41
|
+
def development_theme
|
42
|
+
theme = ShopifyCLI::Theme::DevelopmentTheme.find(@ctx)
|
43
|
+
theme || not_found_error("development")
|
44
|
+
end
|
45
|
+
|
46
|
+
def live_theme
|
47
|
+
ShopifyCLI::Theme::Theme.live(@ctx)
|
48
|
+
end
|
49
|
+
|
50
|
+
def not_found_error(identifier)
|
51
|
+
@ctx.abort(@ctx.message("theme.open.theme_not_found", identifier))
|
52
|
+
end
|
53
|
+
|
54
|
+
def select_theme
|
55
|
+
form = Forms::Select.ask(
|
56
|
+
@ctx,
|
57
|
+
[],
|
58
|
+
title: @ctx.message("theme.open.select"),
|
59
|
+
root: nil
|
60
|
+
)
|
61
|
+
form&.theme
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -45,8 +45,8 @@ module Theme
|
|
45
45
|
ignore_filter.add_patterns(options.flags[:ignores]) if options.flags[:ignores]
|
46
46
|
|
47
47
|
syncer = ShopifyCLI::Theme::Syncer.new(@ctx, theme: theme,
|
48
|
-
|
49
|
-
|
48
|
+
include_filter: include_filter,
|
49
|
+
ignore_filter: ignore_filter)
|
50
50
|
begin
|
51
51
|
syncer.start_threads
|
52
52
|
CLI::UI::Frame.open(@ctx.message("theme.pull.pulling", theme.name, theme.id, theme.shop)) do
|
@@ -55,8 +55,8 @@ module Theme
|
|
55
55
|
ignore_filter.add_patterns(options.flags[:ignores]) if options.flags[:ignores]
|
56
56
|
|
57
57
|
syncer = ShopifyCLI::Theme::Syncer.new(@ctx, theme: theme,
|
58
|
-
|
59
|
-
|
58
|
+
include_filter: include_filter,
|
59
|
+
ignore_filter: ignore_filter)
|
60
60
|
begin
|
61
61
|
syncer.start_threads
|
62
62
|
if options.flags[:json]
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "project_types/theme/presenters/themes_presenter"
|
4
|
+
|
1
5
|
module Theme
|
2
6
|
module Forms
|
3
7
|
class Select < ShopifyCLI::Form
|
@@ -6,53 +10,21 @@ module Theme
|
|
6
10
|
|
7
11
|
def ask
|
8
12
|
self.theme = CLI::UI::Prompt.ask(title, allow_empty: false) do |handler|
|
9
|
-
|
13
|
+
theme_presenters.each do |presenter|
|
14
|
+
theme = presenter.theme
|
15
|
+
|
10
16
|
next if exclude_roles&.include?(theme.role)
|
11
17
|
next if !include_foreign_developments && theme.foreign_development?
|
12
|
-
|
18
|
+
|
19
|
+
handler.option(presenter.to_s(:short)) { theme }
|
13
20
|
end
|
14
21
|
end
|
15
22
|
end
|
16
23
|
|
17
24
|
private
|
18
25
|
|
19
|
-
def
|
20
|
-
|
21
|
-
.sort_by { |theme| theme_sort_order(theme) }
|
22
|
-
end
|
23
|
-
|
24
|
-
def theme_sort_order(theme)
|
25
|
-
case theme.role
|
26
|
-
when "live"
|
27
|
-
0
|
28
|
-
when "unpublished"
|
29
|
-
1
|
30
|
-
when "development"
|
31
|
-
2
|
32
|
-
else
|
33
|
-
3
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def theme_tags(theme)
|
38
|
-
color = case theme.role
|
39
|
-
when "live"
|
40
|
-
"green"
|
41
|
-
when "unpublished"
|
42
|
-
"yellow"
|
43
|
-
when "development"
|
44
|
-
"blue"
|
45
|
-
else
|
46
|
-
"italic"
|
47
|
-
end
|
48
|
-
|
49
|
-
tags = ["{{#{color}:[#{theme.role}]}}"]
|
50
|
-
|
51
|
-
if theme.current_development?
|
52
|
-
tags << "{{cyan:[yours]}}}}"
|
53
|
-
end
|
54
|
-
|
55
|
-
tags.join(" ")
|
26
|
+
def theme_presenters
|
27
|
+
Theme::Presenters::ThemesPresenter.new(ctx, root).all
|
56
28
|
end
|
57
29
|
end
|
58
30
|
end
|
@@ -87,7 +87,7 @@ module Theme
|
|
87
87
|
{{info:View your theme:}}
|
88
88
|
{{underline:%s}}
|
89
89
|
|
90
|
-
{{info:Customize this theme in the
|
90
|
+
{{info:Customize this theme in the Theme Editor:}}
|
91
91
|
{{underline:%s}}
|
92
92
|
DONE
|
93
93
|
name: "Theme name",
|
@@ -130,7 +130,7 @@ module Theme
|
|
130
130
|
SERVING
|
131
131
|
customize_or_preview: <<~CUSTOMIZE_OR_PREVIEW,
|
132
132
|
|
133
|
-
Customize this theme in the
|
133
|
+
Customize this theme in the Theme Editor:
|
134
134
|
{{green:%s}}
|
135
135
|
|
136
136
|
Share this theme preview:
|
@@ -215,6 +215,35 @@ module Theme
|
|
215
215
|
WARN
|
216
216
|
theme_not_found: "Theme \"%s\" doesn't exist",
|
217
217
|
},
|
218
|
+
open: {
|
219
|
+
select: "Select a theme to open",
|
220
|
+
theme_not_found: "Theme \"%s\" doesn't exist",
|
221
|
+
details: <<~DETAILS,
|
222
|
+
{{*}} {{bold:%s}}
|
223
|
+
|
224
|
+
Customize your theme in the Theme Editor:
|
225
|
+
{{green:%s}}
|
226
|
+
|
227
|
+
DETAILS
|
228
|
+
help: <<~HELP,
|
229
|
+
{{command:%s theme open}}: Opens the preview of your remote theme.
|
230
|
+
|
231
|
+
Usage: {{command:%s theme open}}
|
232
|
+
|
233
|
+
Options:
|
234
|
+
{{command:-t, --theme=NAME_OR_ID}} Theme ID or name of your theme.
|
235
|
+
{{command:-l, --live}} Open your live theme.
|
236
|
+
{{command:-d, --development}} Open your development theme.
|
237
|
+
HELP
|
238
|
+
},
|
239
|
+
list: {
|
240
|
+
title: "{{*}} List of {{bold:%s}} themes:",
|
241
|
+
help: <<~HELP,
|
242
|
+
{{command:%s theme list}}: Lists your remote themes.
|
243
|
+
|
244
|
+
Usage: {{command:%s theme list}}
|
245
|
+
HELP
|
246
|
+
},
|
218
247
|
},
|
219
248
|
}.freeze
|
220
249
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "forwardable"
|
4
|
+
|
5
|
+
module Theme
|
6
|
+
module Presenters
|
7
|
+
class ThemePresenter
|
8
|
+
extend Forwardable
|
9
|
+
|
10
|
+
COLOR_BY_ROLE = {
|
11
|
+
"live" => "green",
|
12
|
+
"unpublished" => "yellow",
|
13
|
+
"development" => "blue",
|
14
|
+
}
|
15
|
+
|
16
|
+
attr_reader :theme
|
17
|
+
|
18
|
+
def_delegators :theme, :id, :name, :role
|
19
|
+
|
20
|
+
def initialize(theme)
|
21
|
+
@theme = theme
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s(mode = :long)
|
25
|
+
case mode
|
26
|
+
when :short
|
27
|
+
"{{bold:#{name} #{theme_tags}}}"
|
28
|
+
when :long
|
29
|
+
"{{green:##{id}}} {{bold:#{name} #{theme_tags}}}"
|
30
|
+
else
|
31
|
+
inspect
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def theme_tags
|
38
|
+
tags = ["{{#{tag_color}:[#{role}]}}"]
|
39
|
+
tags << "{{cyan:[yours]}}}}" if theme.current_development?
|
40
|
+
tags.join(" ")
|
41
|
+
end
|
42
|
+
|
43
|
+
def tag_color
|
44
|
+
COLOR_BY_ROLE[role] || "italic"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "theme_presenter"
|
4
|
+
|
5
|
+
module Theme
|
6
|
+
module Presenters
|
7
|
+
class ThemesPresenter
|
8
|
+
ORDER_BY_ROLE = %w(live unpublished development)
|
9
|
+
|
10
|
+
def initialize(ctx, root)
|
11
|
+
@ctx = ctx
|
12
|
+
@root = root
|
13
|
+
end
|
14
|
+
|
15
|
+
def all
|
16
|
+
all_themes
|
17
|
+
.sort_by { |theme| order_by_role(theme) }
|
18
|
+
.map { |theme| ThemePresenter.new(theme) }
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def order_by_role(theme)
|
24
|
+
ORDER_BY_ROLE.index(theme.role) || ORDER_BY_ROLE.size
|
25
|
+
end
|
26
|
+
|
27
|
+
def all_themes
|
28
|
+
ShopifyCLI::Theme::Theme.all(@ctx, root: @root)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/shopify_cli/api.rb
CHANGED
@@ -85,7 +85,7 @@ module ShopifyCLI
|
|
85
85
|
end
|
86
86
|
rescue Errno::ETIMEDOUT, Timeout::Error
|
87
87
|
ctx.debug("timeout in #{method} #{uri} with X-Request-Id: #{headers["X-Request-Id"]}")
|
88
|
-
raise APIRequestTimeoutError
|
88
|
+
raise APIRequestTimeoutError, "Timeout"
|
89
89
|
end.retry_after(APIRequestRetriableError, retries: 3) do |e|
|
90
90
|
sleep(1) if e.is_a?(APIRequestThrottledError)
|
91
91
|
end
|