shopify-cli 2.12.0 → 2.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/CODEOWNERS +5 -0
- data/.github/CONTRIBUTING.md +1 -1
- data/.github/PULL_REQUEST_TEMPLATE.md +1 -1
- data/.github/workflows/shopify.yml +2 -1
- data/.github/workflows/stale.yml +41 -0
- data/.rubocop.yml +1 -1
- data/.ruby-version +1 -1
- data/CHANGELOG.md +36 -0
- data/Gemfile.lock +18 -18
- data/Rakefile +16 -0
- 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-arm-macos-v0.2.1.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-linux-v0.2.1.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-macos-v0.2.1.gz.sha256 +1 -0
- data/ext/javy/hashes/javy-x86_64-windows-v0.2.0.gz.sha256 +1 -0
- data/ext/javy/hashes/javy-x86_64-windows-v0.2.1.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/models/npm_package.rb +19 -1
- data/lib/project_types/extension/models/server_config/development_renderer.rb +4 -3
- data/lib/project_types/extension/models/specification_handlers/checkout_ui_extension.rb +13 -0
- 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/cli.rb +0 -4
- data/lib/project_types/script/commands/create.rb +4 -4
- data/lib/project_types/script/config/extension_points.yml +0 -6
- 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 +9 -26
- 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 +14 -10
- 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/project_creator.rb +0 -16
- data/lib/project_types/script/layers/infrastructure/languages/task_runner.rb +0 -1
- data/lib/project_types/script/layers/infrastructure/languages/typescript_project_creator.rb +19 -4
- data/lib/project_types/script/layers/infrastructure/languages/typescript_task_runner.rb +2 -10
- data/lib/project_types/script/layers/infrastructure/languages/wasm_project_creator.rb +0 -3
- data/lib/project_types/script/layers/infrastructure/languages/wasm_task_runner.rb +1 -1
- data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +3 -21
- data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +14 -26
- data/lib/project_types/script/layers/infrastructure/script_service.rb +4 -2
- data/lib/project_types/script/messages/messages.rb +9 -9
- 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/package.rb +1 -0
- data/lib/project_types/theme/commands/pull.rb +4 -4
- data/lib/project_types/theme/commands/push.rb +4 -4
- data/lib/project_types/theme/conversions/base_glob.rb +20 -5
- data/lib/project_types/theme/forms/select.rb +11 -39
- data/lib/project_types/theme/messages/messages.rb +33 -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/command.rb +1 -7
- data/lib/shopify_cli/commands/app/deploy.rb +0 -1
- data/lib/shopify_cli/constants.rb +2 -2
- data/lib/shopify_cli/context.rb +13 -15
- data/lib/shopify_cli/core/entry_point.rb +1 -1
- data/lib/shopify_cli/core/monorail.rb +14 -6
- data/lib/shopify_cli/environment.rb +19 -11
- data/lib/shopify_cli/exception_reporter.rb +2 -0
- data/lib/shopify_cli/messages/messages.rb +5 -5
- data/lib/shopify_cli/packager.rb +1 -1
- data/lib/shopify_cli/result.rb +14 -0
- data/lib/shopify_cli/services/app/create/node_service.rb +2 -14
- data/lib/shopify_cli/services/app/create/php_service.rb +1 -6
- data/lib/shopify_cli/services/app/create/rails_service.rb +5 -13
- data/lib/shopify_cli/theme/dev_server/hot_reload/remote_file_reloader.rb +5 -5
- data/lib/shopify_cli/theme/dev_server/watcher.rb +10 -2
- data/lib/shopify_cli/theme/development_theme.rb +2 -5
- data/lib/shopify_cli/theme/syncer.rb +27 -32
- data/lib/shopify_cli/theme/theme.rb +16 -27
- data/lib/shopify_cli/theme/theme_admin_api.rb +72 -0
- data/lib/shopify_cli/transform_data_structure.rb +3 -2
- data/lib/shopify_cli/version.rb +1 -1
- data/shipit.yml +3 -0
- data/shopify-cli.gemspec +9 -2
- data/shopify-dev +9 -11
- metadata +21 -9
- data/lib/project_types/rails/ruby.rb +0 -17
- data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb +0 -21
- data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_task_runner.rb +0 -109
|
@@ -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
|
|
@@ -26,11 +26,11 @@ module Theme
|
|
|
26
26
|
parser.on("-d", "--development") { flags[:development] = true }
|
|
27
27
|
parser.on("-o", "--only=PATTERN", Conversions::IncludeGlob) do |pattern|
|
|
28
28
|
flags[:includes] ||= []
|
|
29
|
-
flags[:includes]
|
|
29
|
+
flags[:includes] |= pattern
|
|
30
30
|
end
|
|
31
31
|
parser.on("-x", "--ignore=PATTERN", Conversions::IgnoreGlob) do |pattern|
|
|
32
32
|
flags[:ignores] ||= []
|
|
33
|
-
flags[:ignores]
|
|
33
|
+
flags[:ignores] |= pattern
|
|
34
34
|
end
|
|
35
35
|
end
|
|
36
36
|
|
|
@@ -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
|
|
@@ -30,11 +30,11 @@ module Theme
|
|
|
30
30
|
parser.on("-p", "--publish") { flags[:publish] = true }
|
|
31
31
|
parser.on("-o", "--only=PATTERN", Conversions::IncludeGlob) do |pattern|
|
|
32
32
|
flags[:includes] ||= []
|
|
33
|
-
flags[:includes]
|
|
33
|
+
flags[:includes] |= pattern
|
|
34
34
|
end
|
|
35
35
|
parser.on("-x", "--ignore=PATTERN", Conversions::IgnoreGlob) do |pattern|
|
|
36
36
|
flags[:ignores] ||= []
|
|
37
|
-
flags[:ignores]
|
|
37
|
+
flags[:ignores] |= pattern
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
|
|
@@ -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]
|
|
@@ -10,8 +10,22 @@ module Theme
|
|
|
10
10
|
|
|
11
11
|
def convert(parser)
|
|
12
12
|
argv = parser.default_argv
|
|
13
|
-
|
|
13
|
+
values = []
|
|
14
|
+
|
|
15
|
+
option_indexes(argv).each do |option_index|
|
|
16
|
+
values += option_values(argv, parser, option_index)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
values
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def options
|
|
23
|
+
raise "`#{self.class.name}#options` must be defined"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
14
27
|
|
|
28
|
+
def option_values(argv, parser, option_index)
|
|
15
29
|
return [] if option_index.nil?
|
|
16
30
|
|
|
17
31
|
start_index = option_index + 1
|
|
@@ -26,12 +40,13 @@ module Theme
|
|
|
26
40
|
values
|
|
27
41
|
end
|
|
28
42
|
|
|
29
|
-
def
|
|
30
|
-
|
|
43
|
+
def option_indexes(argv)
|
|
44
|
+
argv
|
|
45
|
+
.each_with_index
|
|
46
|
+
.select { |item, _index| options.include?(item) }
|
|
47
|
+
.map(&:last)
|
|
31
48
|
end
|
|
32
49
|
|
|
33
|
-
private
|
|
34
|
-
|
|
35
50
|
def options_map(parser)
|
|
36
51
|
map = {}
|
|
37
52
|
parser.top.list.each do |option|
|
|
@@ -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
|
|
@@ -7,6 +7,8 @@ module Theme
|
|
|
7
7
|
Suite of commands for developing Shopify themes. See {{command:%1$s theme <command> --help}} for usage of each command.
|
|
8
8
|
Usage: {{command:%1$s theme [ %2$s ]}}
|
|
9
9
|
HELP
|
|
10
|
+
ensure_user_error: "You are not authorized to edit themes on %s.",
|
|
11
|
+
ensure_user_try_this: "Make sure you are a user of that store, and allowed to edit themes.",
|
|
10
12
|
|
|
11
13
|
init: {
|
|
12
14
|
help: <<~HELP,
|
|
@@ -87,7 +89,7 @@ module Theme
|
|
|
87
89
|
{{info:View your theme:}}
|
|
88
90
|
{{underline:%s}}
|
|
89
91
|
|
|
90
|
-
{{info:Customize this theme in the
|
|
92
|
+
{{info:Customize this theme in the Theme Editor:}}
|
|
91
93
|
{{underline:%s}}
|
|
92
94
|
DONE
|
|
93
95
|
name: "Theme name",
|
|
@@ -130,7 +132,7 @@ module Theme
|
|
|
130
132
|
SERVING
|
|
131
133
|
customize_or_preview: <<~CUSTOMIZE_OR_PREVIEW,
|
|
132
134
|
|
|
133
|
-
Customize this theme in the
|
|
135
|
+
Customize this theme in the Theme Editor:
|
|
134
136
|
{{green:%s}}
|
|
135
137
|
|
|
136
138
|
Share this theme preview:
|
|
@@ -215,6 +217,35 @@ module Theme
|
|
|
215
217
|
WARN
|
|
216
218
|
theme_not_found: "Theme \"%s\" doesn't exist",
|
|
217
219
|
},
|
|
220
|
+
open: {
|
|
221
|
+
select: "Select a theme to open",
|
|
222
|
+
theme_not_found: "Theme \"%s\" doesn't exist",
|
|
223
|
+
details: <<~DETAILS,
|
|
224
|
+
{{*}} {{bold:%s}}
|
|
225
|
+
|
|
226
|
+
Customize your theme in the Theme Editor:
|
|
227
|
+
{{green:%s}}
|
|
228
|
+
|
|
229
|
+
DETAILS
|
|
230
|
+
help: <<~HELP,
|
|
231
|
+
{{command:%s theme open}}: Opens the preview of your remote theme.
|
|
232
|
+
|
|
233
|
+
Usage: {{command:%s theme open}}
|
|
234
|
+
|
|
235
|
+
Options:
|
|
236
|
+
{{command:-t, --theme=NAME_OR_ID}} Theme ID or name of your theme.
|
|
237
|
+
{{command:-l, --live}} Open your live theme.
|
|
238
|
+
{{command:-d, --development}} Open your development theme.
|
|
239
|
+
HELP
|
|
240
|
+
},
|
|
241
|
+
list: {
|
|
242
|
+
title: "{{*}} List of {{bold:%s}} themes:",
|
|
243
|
+
help: <<~HELP,
|
|
244
|
+
{{command:%s theme list}}: Lists your remote themes.
|
|
245
|
+
|
|
246
|
+
Usage: {{command:%s theme list}}
|
|
247
|
+
HELP
|
|
248
|
+
},
|
|
218
249
|
},
|
|
219
250
|
}.freeze
|
|
220
251
|
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
|
data/lib/shopify_cli/command.rb
CHANGED
|
@@ -102,16 +102,10 @@ module ShopifyCLI
|
|
|
102
102
|
def check_node_version
|
|
103
103
|
return unless @compatible_node_range
|
|
104
104
|
|
|
105
|
-
context = Context.new
|
|
106
|
-
if context.which("node").nil?
|
|
107
|
-
raise ShopifyCLI::Abort, context.message("core.errors.missing_node")
|
|
108
|
-
end
|
|
109
|
-
|
|
110
105
|
check_version(
|
|
111
106
|
Environment.node_version,
|
|
112
107
|
range: @compatible_node_range,
|
|
113
|
-
runtime: "Node"
|
|
114
|
-
context: context
|
|
108
|
+
runtime: "Node"
|
|
115
109
|
)
|
|
116
110
|
end
|
|
117
111
|
|
data/lib/shopify_cli/context.rb
CHANGED
|
@@ -103,7 +103,7 @@ module ShopifyCLI
|
|
|
103
103
|
# any command run by the context.
|
|
104
104
|
attr_accessor :env
|
|
105
105
|
|
|
106
|
-
def initialize(root: Dir.pwd, env: ($original_env || ENV).
|
|
106
|
+
def initialize(root: Dir.pwd, env: ($original_env || ENV).to_h) # :nodoc:
|
|
107
107
|
self.root = root
|
|
108
108
|
self.env = env
|
|
109
109
|
end
|
|
@@ -164,7 +164,7 @@ module ShopifyCLI
|
|
|
164
164
|
|
|
165
165
|
# will return true while tests are running, either locally or on CI
|
|
166
166
|
def testing?
|
|
167
|
-
ci? || ENV["
|
|
167
|
+
ci? || ENV["SHOPIFY_CLI_TEST"]
|
|
168
168
|
end
|
|
169
169
|
|
|
170
170
|
##
|
|
@@ -570,21 +570,19 @@ module ShopifyCLI
|
|
|
570
570
|
trap("INFO", "DEFAULT")
|
|
571
571
|
|
|
572
572
|
fork do
|
|
573
|
-
|
|
574
|
-
|
|
573
|
+
r, w = IO.pipe
|
|
574
|
+
@signal = false
|
|
575
|
+
trap("SIGINFO") do
|
|
576
|
+
@signal = true
|
|
577
|
+
w.write(0)
|
|
578
|
+
end
|
|
579
|
+
while r.read(1)
|
|
580
|
+
next unless @signal
|
|
575
581
|
@signal = false
|
|
576
|
-
|
|
577
|
-
@signal = true
|
|
578
|
-
w.write(0)
|
|
579
|
-
end
|
|
580
|
-
while r.read(1)
|
|
581
|
-
next unless @signal
|
|
582
|
-
@signal = false
|
|
583
|
-
yield
|
|
584
|
-
end
|
|
585
|
-
rescue Interrupt
|
|
586
|
-
exit(0)
|
|
582
|
+
yield
|
|
587
583
|
end
|
|
584
|
+
rescue Interrupt
|
|
585
|
+
exit(0)
|
|
588
586
|
end
|
|
589
587
|
end
|
|
590
588
|
|
|
@@ -5,7 +5,7 @@ module ShopifyCLI
|
|
|
5
5
|
module EntryPoint
|
|
6
6
|
class << self
|
|
7
7
|
def call(args, ctx = Context.new)
|
|
8
|
-
if ctx.development?
|
|
8
|
+
if ctx.development? && !ctx.testing?
|
|
9
9
|
ctx.warn(
|
|
10
10
|
ctx.message("core.warning.development_version", File.join(ShopifyCLI::ROOT, "bin", ShopifyCLI::TOOL_NAME))
|
|
11
11
|
)
|
|
@@ -17,11 +17,7 @@ module ShopifyCLI
|
|
|
17
17
|
|
|
18
18
|
def log(name, args, &block) # rubocop:disable Lint/UnusedMethodArgument
|
|
19
19
|
command, command_name = Commands::Registry.lookup_command(name)
|
|
20
|
-
|
|
21
|
-
if command
|
|
22
|
-
subcommand, subcommand_name = command.subcommand_registry.lookup_command(args.first)
|
|
23
|
-
final_command << subcommand_name if subcommand
|
|
24
|
-
end
|
|
20
|
+
full_command = self.full_command(command, args, resolved_command: [command_name])
|
|
25
21
|
|
|
26
22
|
start_time = now_in_milliseconds
|
|
27
23
|
err = nil
|
|
@@ -35,9 +31,21 @@ module ShopifyCLI
|
|
|
35
31
|
# If there's an error, we don't prompt from here and we let the exception
|
|
36
32
|
# reporter do that.
|
|
37
33
|
if report?(prompt: err.nil?)
|
|
38
|
-
send_event(start_time,
|
|
34
|
+
send_event(start_time, full_command, args - full_command, err&.message)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def full_command(command, args, resolved_command:)
|
|
40
|
+
resolved_command = resolved_command.dup
|
|
41
|
+
if command
|
|
42
|
+
subcommand, subcommand_name = command.subcommand_registry.lookup_command(args.first)
|
|
43
|
+
resolved_command << subcommand_name if subcommand
|
|
44
|
+
if subcommand&.subcommand_registry
|
|
45
|
+
resolved_command = full_command(subcommand, args.drop(1), resolved_command: resolved_command)
|
|
39
46
|
end
|
|
40
47
|
end
|
|
48
|
+
resolved_command
|
|
41
49
|
end
|
|
42
50
|
|
|
43
51
|
private
|
|
@@ -12,23 +12,31 @@ module ShopifyCLI
|
|
|
12
12
|
]
|
|
13
13
|
|
|
14
14
|
def self.ruby_version(context: Context.new)
|
|
15
|
-
|
|
16
|
-
raise ShopifyCLI::Abort,
|
|
17
|
-
|
|
18
|
-
::Semantic::Version.new(
|
|
15
|
+
output, status = context.capture2e("ruby", "--version")
|
|
16
|
+
raise ShopifyCLI::Abort, context.message("core.errors.missing_ruby") unless status.success?
|
|
17
|
+
version = output.match(/ruby (\d+\.\d+\.\d+)/)[1]
|
|
18
|
+
::Semantic::Version.new(version)
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def self.node_version(context: Context.new)
|
|
22
|
-
|
|
23
|
-
raise ShopifyCLI::Abort,
|
|
24
|
-
|
|
25
|
-
::Semantic::Version.new(
|
|
22
|
+
output, status = context.capture2e("node", "--version")
|
|
23
|
+
raise ShopifyCLI::Abort, context.message("core.errors.missing_node") unless status.success?
|
|
24
|
+
version = output.match(/v(\d+\.\d+\.\d+)/)[1]
|
|
25
|
+
::Semantic::Version.new(version)
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def self.npm_version(context: Context.new)
|
|
29
|
-
|
|
30
|
-
raise ShopifyCLI::Abort,
|
|
31
|
-
|
|
29
|
+
output, status = context.capture2e("npm", "--version")
|
|
30
|
+
raise ShopifyCLI::Abort, context.message("core.errors.missing_npm") unless status.success?
|
|
31
|
+
version = output.match(/(\d+\.\d+\.\d+)/)[1]
|
|
32
|
+
::Semantic::Version.new(version)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.rails_version(context: Context.new)
|
|
36
|
+
output, status = context.capture2e("rails", "--version")
|
|
37
|
+
context.abort(context.message("core.app.create.rails.error.install_failure", "rails")) unless status.success?
|
|
38
|
+
version = output.match(/Rails (\d+\.\d+\.\d+)/)[1]
|
|
39
|
+
::Semantic::Version.new(version)
|
|
32
40
|
end
|
|
33
41
|
|
|
34
42
|
def self.interactive=(interactive)
|