shopify-cli 2.11.2 → 2.14.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/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
|
|