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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/shopify.yml +2 -1
  3. data/.rubocop.yml +1 -1
  4. data/.ruby-version +1 -1
  5. data/CHANGELOG.md +10 -0
  6. data/Gemfile.lock +14 -14
  7. data/bin/shopify +4 -4
  8. data/dev.yml +1 -1
  9. data/ext/javy/hashes/javy-arm-macos-v0.2.0.gz.sha256 +1 -0
  10. data/ext/javy/hashes/javy-x86_64-linux-v0.2.0.gz.sha256 +1 -0
  11. data/ext/javy/hashes/javy-x86_64-macos-v0.2.0.gz.sha256 +1 -0
  12. data/ext/javy/hashes/javy-x86_64-windows-v0.2.0.gz.sha256 +1 -0
  13. data/ext/javy/version +1 -1
  14. data/lib/project_types/extension/features/argo_setup_steps.rb +4 -6
  15. data/lib/project_types/extension/tasks/configure_features.rb +15 -2
  16. data/lib/project_types/extension/tasks/convert_server_config.rb +2 -1
  17. data/lib/project_types/script/commands/create.rb +4 -4
  18. data/lib/project_types/script/errors.rb +1 -1
  19. data/lib/project_types/script/forms/create.rb +7 -7
  20. data/lib/project_types/script/layers/application/build_script.rb +22 -24
  21. data/lib/project_types/script/layers/application/create_script.rb +9 -10
  22. data/lib/project_types/script/layers/application/project_dependencies.rb +12 -14
  23. data/lib/project_types/script/layers/application/push_script.rb +2 -0
  24. data/lib/project_types/script/layers/domain/errors.rb +3 -3
  25. data/lib/project_types/script/layers/domain/push_package.rb +6 -0
  26. data/lib/project_types/script/layers/domain/script_config.rb +2 -4
  27. data/lib/project_types/script/layers/domain/script_project.rb +3 -2
  28. data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb +19 -4
  29. data/lib/project_types/script/layers/infrastructure/languages/project_creator.rb +0 -15
  30. data/lib/project_types/script/layers/infrastructure/languages/typescript_project_creator.rb +19 -4
  31. data/lib/project_types/script/layers/infrastructure/languages/wasm_project_creator.rb +0 -3
  32. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +4 -0
  33. data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +13 -25
  34. data/lib/project_types/script/layers/infrastructure/script_service.rb +4 -2
  35. data/lib/project_types/script/messages/messages.rb +7 -7
  36. data/lib/project_types/script/ui/error_handler.rb +4 -4
  37. data/lib/project_types/script/ui/strict_spinner.rb +4 -6
  38. data/lib/project_types/theme/cli.rb +2 -0
  39. data/lib/project_types/theme/commands/common/root_helper.rb +11 -5
  40. data/lib/project_types/theme/commands/list.rb +34 -0
  41. data/lib/project_types/theme/commands/open.rb +65 -0
  42. data/lib/project_types/theme/commands/pull.rb +2 -2
  43. data/lib/project_types/theme/commands/push.rb +2 -2
  44. data/lib/project_types/theme/forms/select.rb +11 -39
  45. data/lib/project_types/theme/messages/messages.rb +31 -2
  46. data/lib/project_types/theme/presenters/theme_presenter.rb +48 -0
  47. data/lib/project_types/theme/presenters/themes_presenter.rb +32 -0
  48. data/lib/shopify_cli/api.rb +1 -1
  49. data/lib/shopify_cli/constants.rb +2 -2
  50. data/lib/shopify_cli/context.rb +11 -13
  51. data/lib/shopify_cli/services/app/create/rails_service.rb +1 -1
  52. data/lib/shopify_cli/theme/syncer.rb +7 -7
  53. data/lib/shopify_cli/version.rb +1 -1
  54. data/shopify-dev +9 -11
  55. 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
@@ -5,9 +5,6 @@ module Script
5
5
  module Infrastructure
6
6
  module Languages
7
7
  class WasmProjectCreator < ProjectCreator
8
- def self.config_file
9
- "script.config.yml"
10
- end
11
8
  end
12
9
  end
13
10
  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(script_name:, extension_point_type:, language:)
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
- script_name: script_name,
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
- script_name: script_name,
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
- script_name: script_name,
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 script_name
115
- project_config_value!("script_name")
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: script_config.title,
30
- description: script_config.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 script_name.",
27
+ "extension_point_type or title.",
28
28
  invalid_context_help: "Add these values.",
29
29
 
30
- invalid_script_name_cause: "Script name contains unsupported characters.",
31
- invalid_script_name_help: "Use only numbers, letters, hyphens, or underscores.",
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 name already exists.",
41
- project_exists_help: "Choose a different name for your script.",
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:--name=NAME}} Script project name.
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
- script_name: "What do you want to name your script?",
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::InvalidScriptNameError
62
+ when Errors::InvalidScriptTitleError
63
63
  {
64
- cause_of_error: ShopifyCLI::Context.message("script.error.invalid_script_name_cause"),
65
- help_suggestion: ShopifyCLI::Context.message("script.error.invalid_script_name_help"),
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.script_name,
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
- begin
12
- yield(*args)
13
- rescue StandardError => e
14
- exception = e
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
- option = option_by_key[element]
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 unless option.arg.nil?
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
- option_by_key[element].nil?
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
- include_filter: include_filter,
49
- ignore_filter: ignore_filter)
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
- include_filter: include_filter,
59
- ignore_filter: ignore_filter)
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
- themes.each do |theme|
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
- handler.option("#{theme.name} #{theme_tags(theme)}") { theme }
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 themes
20
- @themes ||= ShopifyCLI::Theme::Theme.all(@ctx, root: root)
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 Online Store Editor:}}
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 Online Store Editor:
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
@@ -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.new("Timeout")
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
@@ -61,12 +61,12 @@ module ShopifyCLI
61
61
  module SupportedVersions
62
62
  module Ruby
63
63
  FROM = "2.6.6"
64
- TO = "3.1.0"
64
+ TO = "3.2.0"
65
65
  end
66
66
 
67
67
  module Node
68
68
  FROM = "14.5.0"
69
- TO = "17.0.0"
69
+ TO = "18.0.0"
70
70
  end
71
71
  end
72
72