shopify-cli 2.11.2 → 2.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/CODEOWNERS +5 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +1 -1
- data/.github/workflows/shopify.yml +2 -1
- data/.rubocop.yml +1 -1
- data/.ruby-version +1 -1
- data/CHANGELOG.md +44 -1
- data/Gemfile.lock +18 -18
- data/Rakefile +16 -0
- data/bin/shopify +12 -8
- data/dev.yml +1 -1
- data/docs/users/installation.md +1 -44
- 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 +114 -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 +2 -4
- data/lib/project_types/script/commands/create.rb +5 -5
- data/lib/project_types/script/commands/push.rb +4 -6
- data/lib/project_types/script/config/extension_points.yml +0 -10
- data/lib/project_types/script/errors.rb +1 -1
- data/lib/project_types/script/forms/create.rb +7 -20
- data/lib/project_types/script/layers/application/build_script.rb +9 -26
- data/lib/project_types/script/layers/application/connect_app.rb +3 -2
- 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/errors.rb +11 -0
- 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/tool_version_checker.rb +26 -0
- data/lib/project_types/script/layers/infrastructure/languages/typescript_project_creator.rb +22 -10
- data/lib/project_types/script/layers/infrastructure/languages/typescript_task_runner.rb +32 -29
- 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/loaders/project.rb +8 -7
- data/lib/project_types/script/messages/messages.rb +22 -21
- data/lib/project_types/script/ui/error_handler.rb +17 -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 +71 -0
- data/lib/project_types/theme/commands/init.rb +2 -0
- 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 +18 -10
- data/lib/project_types/theme/commands/push.rb +17 -9
- data/lib/project_types/theme/commands/serve.rb +6 -2
- data/lib/project_types/theme/conversions/base_glob.rb +50 -0
- data/lib/project_types/theme/conversions/ignore_glob.rb +15 -0
- data/lib/project_types/theme/conversions/include_glob.rb +15 -0
- data/lib/project_types/theme/forms/select.rb +11 -39
- data/lib/project_types/theme/messages/messages.rb +38 -7
- 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/commands/app/create/node.rb +1 -0
- data/lib/shopify_cli/commands/app/create/php.rb +1 -0
- data/lib/shopify_cli/commands/app/create/rails.rb +1 -0
- data/lib/shopify_cli/commands/app/deploy.rb +1 -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 +6 -0
- data/lib/shopify_cli/exception_reporter.rb +2 -0
- data/lib/shopify_cli/git.rb +9 -1
- data/lib/shopify_cli/messages/messages.rb +21 -1
- data/lib/shopify_cli/packager.rb +1 -1
- data/lib/shopify_cli/result.rb +14 -0
- data/lib/shopify_cli/services/app/create/rails_service.rb +1 -1
- data/lib/shopify_cli/tasks/ensure_git_dependency.rb +14 -0
- data/lib/shopify_cli/tasks.rb +1 -0
- data/lib/shopify_cli/theme/dev_server/hot_reload/remote_file_reloader.rb +5 -5
- data/lib/shopify_cli/theme/dev_server/proxy.rb +14 -2
- 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/include_filter.rb +4 -2
- data/lib/shopify_cli/theme/syncer.rb +40 -36
- data/lib/shopify_cli/theme/theme.rb +16 -27
- data/lib/shopify_cli/theme/theme_admin_api.rb +71 -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 +26 -8
- data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb +0 -25
- data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_task_runner.rb +0 -98
@@ -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
|
@@ -4,41 +4,49 @@ require "shopify_cli/theme/development_theme"
|
|
4
4
|
require "shopify_cli/theme/ignore_filter"
|
5
5
|
require "shopify_cli/theme/include_filter"
|
6
6
|
require "shopify_cli/theme/syncer"
|
7
|
+
require "project_types/theme/commands/common/root_helper"
|
8
|
+
require "project_types/theme/conversions/include_glob"
|
9
|
+
require "project_types/theme/conversions/ignore_glob"
|
7
10
|
|
8
11
|
module Theme
|
9
12
|
class Command
|
10
13
|
class Pull < ShopifyCLI::Command::SubCommand
|
14
|
+
include Common::RootHelper
|
15
|
+
|
11
16
|
recommend_default_ruby_range
|
12
17
|
|
13
18
|
options do |parser, flags|
|
19
|
+
Conversions::IncludeGlob.register(parser)
|
20
|
+
Conversions::IgnoreGlob.register(parser)
|
21
|
+
|
14
22
|
parser.on("-n", "--nodelete") { flags[:nodelete] = true }
|
15
23
|
parser.on("-i", "--themeid=ID") { |theme_id| flags[:theme_id] = theme_id }
|
16
24
|
parser.on("-t", "--theme=NAME_OR_ID") { |theme| flags[:theme] = theme }
|
17
25
|
parser.on("-l", "--live") { flags[:live] = true }
|
18
26
|
parser.on("-d", "--development") { flags[:development] = true }
|
19
|
-
parser.on("-o", "--only=PATTERN") do |pattern|
|
27
|
+
parser.on("-o", "--only=PATTERN", Conversions::IncludeGlob) do |pattern|
|
20
28
|
flags[:includes] ||= []
|
21
|
-
flags[:includes]
|
29
|
+
flags[:includes] += pattern
|
22
30
|
end
|
23
|
-
parser.on("-x", "--ignore=PATTERN") do |pattern|
|
31
|
+
parser.on("-x", "--ignore=PATTERN", Conversions::IgnoreGlob) do |pattern|
|
24
32
|
flags[:ignores] ||= []
|
25
|
-
flags[:ignores]
|
33
|
+
flags[:ignores] += pattern
|
26
34
|
end
|
27
35
|
end
|
28
36
|
|
29
|
-
def call(
|
30
|
-
root =
|
37
|
+
def call(_args, name)
|
38
|
+
root = root_value(options, name)
|
31
39
|
delete = !options.flags[:nodelete]
|
32
40
|
theme = find_theme(root, **options.flags)
|
33
41
|
return if theme.nil?
|
34
42
|
|
35
|
-
include_filter = ShopifyCLI::Theme::IncludeFilter.new(options.flags[:includes])
|
43
|
+
include_filter = ShopifyCLI::Theme::IncludeFilter.new(root, options.flags[:includes])
|
36
44
|
ignore_filter = ShopifyCLI::Theme::IgnoreFilter.from_path(root)
|
37
45
|
ignore_filter.add_patterns(options.flags[:ignores]) if options.flags[:ignores]
|
38
46
|
|
39
47
|
syncer = ShopifyCLI::Theme::Syncer.new(@ctx, theme: theme,
|
40
|
-
|
41
|
-
|
48
|
+
include_filter: include_filter,
|
49
|
+
ignore_filter: ignore_filter)
|
42
50
|
begin
|
43
51
|
syncer.start_threads
|
44
52
|
CLI::UI::Frame.open(@ctx.message("theme.pull.pulling", theme.name, theme.id, theme.shop)) do
|
@@ -75,7 +83,7 @@ module Theme
|
|
75
83
|
|
76
84
|
if development
|
77
85
|
dev_theme = ShopifyCLI::Theme::DevelopmentTheme.find(@ctx, root: root)
|
78
|
-
return dev_theme || @ctx.abort(@ctx.message("theme.pull.theme_not_found",
|
86
|
+
return dev_theme || @ctx.abort(@ctx.message("theme.pull.theme_not_found", "development"))
|
79
87
|
end
|
80
88
|
|
81
89
|
select_theme(root)
|
@@ -4,13 +4,21 @@ require "shopify_cli/theme/development_theme"
|
|
4
4
|
require "shopify_cli/theme/ignore_filter"
|
5
5
|
require "shopify_cli/theme/include_filter"
|
6
6
|
require "shopify_cli/theme/syncer"
|
7
|
+
require "project_types/theme/commands/common/root_helper"
|
8
|
+
require "project_types/theme/conversions/include_glob"
|
9
|
+
require "project_types/theme/conversions/ignore_glob"
|
7
10
|
|
8
11
|
module Theme
|
9
12
|
class Command
|
10
13
|
class Push < ShopifyCLI::Command::SubCommand
|
14
|
+
include Common::RootHelper
|
15
|
+
|
11
16
|
recommend_default_ruby_range
|
12
17
|
|
13
18
|
options do |parser, flags|
|
19
|
+
Conversions::IncludeGlob.register(parser)
|
20
|
+
Conversions::IgnoreGlob.register(parser)
|
21
|
+
|
14
22
|
parser.on("-n", "--nodelete") { flags[:nodelete] = true }
|
15
23
|
parser.on("-i", "--themeid=ID") { |theme_id| flags[:theme_id] = theme_id }
|
16
24
|
parser.on("-t", "--theme=NAME_OR_ID") { |theme| flags[:theme] = theme }
|
@@ -20,18 +28,18 @@ module Theme
|
|
20
28
|
parser.on("-j", "--json") { flags[:json] = true }
|
21
29
|
parser.on("-a", "--allow-live") { flags[:allow_live] = true }
|
22
30
|
parser.on("-p", "--publish") { flags[:publish] = true }
|
23
|
-
parser.on("-o", "--only=PATTERN") do |pattern|
|
31
|
+
parser.on("-o", "--only=PATTERN", Conversions::IncludeGlob) do |pattern|
|
24
32
|
flags[:includes] ||= []
|
25
|
-
flags[:includes]
|
33
|
+
flags[:includes] += pattern
|
26
34
|
end
|
27
|
-
parser.on("-x", "--ignore=PATTERN") do |pattern|
|
35
|
+
parser.on("-x", "--ignore=PATTERN", Conversions::IgnoreGlob) do |pattern|
|
28
36
|
flags[:ignores] ||= []
|
29
|
-
flags[:ignores]
|
37
|
+
flags[:ignores] += pattern
|
30
38
|
end
|
31
39
|
end
|
32
40
|
|
33
|
-
def call(
|
34
|
-
root =
|
41
|
+
def call(_args, name)
|
42
|
+
root = root_value(options, name)
|
35
43
|
delete = !options.flags[:nodelete]
|
36
44
|
theme = find_theme(root, **options.flags)
|
37
45
|
return if theme.nil?
|
@@ -42,13 +50,13 @@ module Theme
|
|
42
50
|
return unless CLI::UI::Prompt.confirm(question)
|
43
51
|
end
|
44
52
|
|
45
|
-
include_filter = ShopifyCLI::Theme::IncludeFilter.new(options.flags[:includes])
|
53
|
+
include_filter = ShopifyCLI::Theme::IncludeFilter.new(root, options.flags[:includes])
|
46
54
|
ignore_filter = ShopifyCLI::Theme::IgnoreFilter.from_path(root)
|
47
55
|
ignore_filter.add_patterns(options.flags[:ignores]) if options.flags[:ignores]
|
48
56
|
|
49
57
|
syncer = ShopifyCLI::Theme::Syncer.new(@ctx, theme: theme,
|
50
|
-
|
51
|
-
|
58
|
+
include_filter: include_filter,
|
59
|
+
ignore_filter: ignore_filter)
|
52
60
|
begin
|
53
61
|
syncer.start_threads
|
54
62
|
if options.flags[:json]
|
@@ -1,9 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require "shopify_cli/theme/dev_server"
|
3
|
+
require "project_types/theme/commands/common/root_helper"
|
3
4
|
|
4
5
|
module Theme
|
5
6
|
class Command
|
6
7
|
class Serve < ShopifyCLI::Command::SubCommand
|
8
|
+
include Common::RootHelper
|
9
|
+
|
7
10
|
recommend_default_ruby_range
|
8
11
|
|
9
12
|
DEFAULT_HTTP_HOST = "127.0.0.1"
|
@@ -15,10 +18,11 @@ module Theme
|
|
15
18
|
parser.on("--live-reload=MODE") { |mode| flags[:mode] = as_reload_mode(mode) }
|
16
19
|
end
|
17
20
|
|
18
|
-
def call(
|
21
|
+
def call(_args, name)
|
22
|
+
root = root_value(options, name)
|
19
23
|
flags = options.flags.dup
|
20
24
|
host = flags[:host] || DEFAULT_HTTP_HOST
|
21
|
-
ShopifyCLI::Theme::DevServer.start(@ctx,
|
25
|
+
ShopifyCLI::Theme::DevServer.start(@ctx, root, host: host, **flags) do |syncer|
|
22
26
|
UI::SyncProgressBar.new(syncer).progress(:upload_theme!, delay_low_priority_files: true)
|
23
27
|
end
|
24
28
|
rescue ShopifyCLI::Theme::DevServer::AddressBindingError
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Theme
|
4
|
+
module Conversions
|
5
|
+
class BaseGlob
|
6
|
+
class << self
|
7
|
+
def register(parser)
|
8
|
+
parser.accept(self) { |_val| convert(parser) }
|
9
|
+
end
|
10
|
+
|
11
|
+
def convert(parser)
|
12
|
+
argv = parser.default_argv
|
13
|
+
option_index = argv.index { |v| options.include?(v) }
|
14
|
+
|
15
|
+
return [] if option_index.nil?
|
16
|
+
|
17
|
+
start_index = option_index + 1
|
18
|
+
option_by_key = options_map(parser)
|
19
|
+
values = []
|
20
|
+
|
21
|
+
argv[start_index..-1].each do |value|
|
22
|
+
return values unless option_by_key[value].nil?
|
23
|
+
values << value
|
24
|
+
end
|
25
|
+
|
26
|
+
values
|
27
|
+
end
|
28
|
+
|
29
|
+
def options
|
30
|
+
raise "`#{self.class.name}#options` must be defined"
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def options_map(parser)
|
36
|
+
map = {}
|
37
|
+
parser.top.list.each do |option|
|
38
|
+
map[option.short.first] = option
|
39
|
+
map[option.long.first] = option
|
40
|
+
end
|
41
|
+
map
|
42
|
+
end
|
43
|
+
|
44
|
+
def parameter?(value)
|
45
|
+
value.start_with?("-")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -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,
|
@@ -65,8 +67,8 @@ module Theme
|
|
65
67
|
{{command:-j, --json}} Output JSON instead of a UI.
|
66
68
|
{{command:-a, --allow-live}} Allow push to a live theme.
|
67
69
|
{{command:-p, --publish}} Publish as the live theme after uploading.
|
68
|
-
{{command:-o, --only}} Upload only the specified files.
|
69
|
-
{{command:-x, --ignore}} Skip uploading the specified files.
|
70
|
+
{{command:-o, --only}} Upload only the specified files (Multiple flags allowed).
|
71
|
+
{{command:-x, --ignore}} Skip uploading the specified files (Multiple flags allowed).
|
70
72
|
|
71
73
|
Run without options to select theme from a list.
|
72
74
|
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",
|
@@ -96,7 +98,7 @@ module Theme
|
|
96
98
|
help: <<~HELP,
|
97
99
|
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.
|
98
100
|
|
99
|
-
Usage: {{command:%s theme serve}}
|
101
|
+
Usage: {{command:%s theme serve [ ROOT ]}}
|
100
102
|
|
101
103
|
Options:
|
102
104
|
{{command:--port=PORT}} Local port to serve theme preview from.
|
@@ -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:
|
@@ -202,8 +204,8 @@ module Theme
|
|
202
204
|
{{command:-l, --live}} Pull theme files from your remote live theme.
|
203
205
|
{{command:-d, --development}} Pull theme files from your remote development theme.
|
204
206
|
{{command:-n, --nodelete}} Runs the pull command without deleting local files.
|
205
|
-
{{command:-o, --only}} Download only the specified files.
|
206
|
-
{{command:-x, --ignore}} Skip downloading the specified files.
|
207
|
+
{{command:-o, --only}} Download only the specified files (Multiple flags allowed).
|
208
|
+
{{command:-x, --ignore}} Skip downloading the specified files (Multiple flags allowed).
|
207
209
|
|
208
210
|
Run without options to select theme from a list.
|
209
211
|
HELP
|
@@ -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/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
|
|