shopify-cli 2.11.2 → 2.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -1
  3. data/Gemfile.lock +1 -1
  4. data/bin/shopify +8 -4
  5. data/docs/users/installation.md +1 -44
  6. data/lib/project_types/extension/models/specification_handlers/checkout_ui_extension.rb +114 -0
  7. data/lib/project_types/script/cli.rb +2 -0
  8. data/lib/project_types/script/commands/create.rb +2 -2
  9. data/lib/project_types/script/commands/push.rb +4 -6
  10. data/lib/project_types/script/config/extension_points.yml +0 -4
  11. data/lib/project_types/script/forms/create.rb +1 -14
  12. data/lib/project_types/script/layers/application/connect_app.rb +3 -2
  13. data/lib/project_types/script/layers/infrastructure/errors.rb +11 -0
  14. data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb +2 -6
  15. data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_task_runner.rb +29 -18
  16. data/lib/project_types/script/layers/infrastructure/languages/tool_version_checker.rb +26 -0
  17. data/lib/project_types/script/layers/infrastructure/languages/typescript_project_creator.rb +3 -6
  18. data/lib/project_types/script/layers/infrastructure/languages/typescript_task_runner.rb +30 -19
  19. data/lib/project_types/script/loaders/project.rb +8 -7
  20. data/lib/project_types/script/messages/messages.rb +13 -12
  21. data/lib/project_types/script/ui/error_handler.rb +13 -0
  22. data/lib/project_types/theme/commands/common/root_helper.rb +65 -0
  23. data/lib/project_types/theme/commands/init.rb +2 -0
  24. data/lib/project_types/theme/commands/pull.rb +16 -8
  25. data/lib/project_types/theme/commands/push.rb +15 -7
  26. data/lib/project_types/theme/commands/serve.rb +6 -2
  27. data/lib/project_types/theme/conversions/base_glob.rb +50 -0
  28. data/lib/project_types/theme/conversions/ignore_glob.rb +15 -0
  29. data/lib/project_types/theme/conversions/include_glob.rb +15 -0
  30. data/lib/project_types/theme/messages/messages.rb +5 -5
  31. data/lib/shopify_cli/commands/app/create/node.rb +1 -0
  32. data/lib/shopify_cli/commands/app/create/php.rb +1 -0
  33. data/lib/shopify_cli/commands/app/create/rails.rb +1 -0
  34. data/lib/shopify_cli/commands/app/deploy.rb +1 -0
  35. data/lib/shopify_cli/environment.rb +6 -0
  36. data/lib/shopify_cli/git.rb +9 -1
  37. data/lib/shopify_cli/messages/messages.rb +21 -1
  38. data/lib/shopify_cli/tasks/ensure_git_dependency.rb +14 -0
  39. data/lib/shopify_cli/tasks.rb +1 -0
  40. data/lib/shopify_cli/theme/dev_server/proxy.rb +14 -2
  41. data/lib/shopify_cli/theme/include_filter.rb +4 -2
  42. data/lib/shopify_cli/theme/syncer.rb +13 -4
  43. data/lib/shopify_cli/version.rb +1 -1
  44. metadata +8 -2
@@ -20,21 +20,22 @@ module Script
20
20
  project.env = env
21
21
  project
22
22
  rescue SmartProperties::InitializationError, SmartProperties::InvalidValueError => error
23
- handle_error(error, context: context, env_file_present: env_file_present)
23
+ handle_error(error, context: context)
24
24
  end
25
25
 
26
- def self.handle_error(error, context:, env_file_present:)
27
- if env_file_present
26
+ def self.handle_error(error, context:)
27
+ if ShopifyCLI::Environment.interactive?
28
28
  properties_hash = { api_key: "SHOPIFY_API_KEY", secret: "SHOPIFY_API_SECRET" }
29
29
  missing_env_variables = error.properties.map { |p| properties_hash[p.name] }.compact.join(", ")
30
- raise ShopifyCLI::Abort,
31
- context.message("script.error.missing_env_file_variables", missing_env_variables, ShopifyCLI::TOOL_NAME)
30
+ message = context.message("script.error.missing_env_file_variables", missing_env_variables)
31
+ message += context.message("script.error.missing_env_file_variables_solution", ShopifyCLI::TOOL_NAME)
32
32
  else
33
33
  properties_hash = { api_key: "--api-key", secret: "--api-secret" }
34
34
  missing_options = error.properties.map { |p| properties_hash[p.name] }.compact.join(", ")
35
- raise ShopifyCLI::Abort, context.message("script.error.missing_push_options", missing_options,
36
- ShopifyCli::TOOL_NAME)
35
+ message = context.message("script.error.missing_push_options_ci", missing_options)
36
+ message += context.message("script.error.missing_push_options_ci_solution", ShopifyCLI::TOOL_NAME)
37
37
  end
38
+ raise ShopifyCLI::Abort, message
38
39
  end
39
40
 
40
41
  def self.env_file_exists?(directory)
@@ -113,6 +113,10 @@ module Script
113
113
  dependency_install_cause: "Something went wrong while installing the needed dependencies.",
114
114
  dependency_install_help: "Correct the errors.",
115
115
 
116
+ invalid_environment_cause: "Your environment %{tool} version, %{env_version}, "\
117
+ "is too low. It must be at least %{minimum_version}.",
118
+ invalid_environment_help: "Update %{tool}.",
119
+
116
120
  failed_api_request_cause: "Something went wrong while communicating with Shopify.",
117
121
  failed_api_request_help: "Try again.",
118
122
 
@@ -150,11 +154,13 @@ module Script
150
154
  language_library_for_api_not_found_cause: "Script can’t be pushed because the %{language} library for API %{api} is missing.",
151
155
  language_library_for_api_not_found_help: "Make sure extension_point.yml contains the correct API library.",
152
156
  no_scripts_found_in_app: "The selected apps have no scripts. Please, create them first on the partners' dashboard.",
153
- missing_env_file_variables: "The following are missing in the .env file: %s."\
154
- " To add it, run {{command:%s script connect}}",
155
- missing_push_options: "The following are missing: %s. "\
156
- "To add them to a CI environment:\n\t1. Run a connect command {{command:%s script connect}}\n\t2. Navigate to the .env file at the root of your project\n\t"\
157
- "3. Copy the missing values, then pass them through as arguments.",
157
+ missing_push_options_ci: "The following are missing: %s. ",
158
+ missing_push_options_ci_solution: "To add them to a CI environment:\n\t1. Run a connect command " \
159
+ "({{command:%1$s script connect}})\n\t2. Navigate to the .env file at the root of your project\n\t" \
160
+ "3. Copy the missing values and pass them through as arguments in {{command:%1$s script push}}",
161
+ missing_env_file_variables: "The following are missing in the .env file: %s. ",
162
+ missing_env_file_variables_solution: "To add it, connect your script with " \
163
+ "{{command:%1$s script connect}} ",
158
164
  },
159
165
 
160
166
  create: {
@@ -164,7 +170,7 @@ module Script
164
170
  Options:
165
171
  {{command:--name=NAME}} Script project name.
166
172
  {{command:--api=TYPE}} Script API name. Supported values: %2$s.
167
- {{command:--language=LANGUAGE}} Programming language. Supported values: %3$s.
173
+ {{command:--language=LANGUAGE}} Programming language. Defaults to wasm. Supported values: %3$s.
168
174
  HELP
169
175
 
170
176
  error: {
@@ -191,9 +197,7 @@ module Script
191
197
  HELP
192
198
 
193
199
  error: {
194
- operation_failed_no_uuid: "UUID is required to push in a CI environment.",
195
- operation_failed_with_api_key: "Couldn't push script to app (API key: %{api_key}).",
196
- operation_failed_no_api_key: "Couldn't push script to app.",
200
+ operation_failed: "Couldn't push script to app.",
197
201
  },
198
202
 
199
203
  script_pushed: "{{v}} Script pushed to app (API key: %{api_key}).",
@@ -206,8 +210,6 @@ module Script
206
210
  HELP
207
211
  error: {
208
212
  operation_failed: "Couldn't connect script to app.",
209
- missing_env_file_variables: "The following variables are missing in the .env file: %s."\
210
- " To connect the script to an app, enter the value into the .env file or delete the .env file, and then run {{command:%s script connect}}",
211
213
  },
212
214
  },
213
215
  javy: {
@@ -233,7 +235,6 @@ module Script
233
235
  forms: {
234
236
  create: {
235
237
  select_extension_point: "Which Script API do you want to use?",
236
- select_language: "Which language do you want to use?",
237
238
  script_name: "What do you want to name your script?",
238
239
  },
239
240
  },
@@ -237,6 +237,19 @@ module Script
237
237
  ),
238
238
  help_suggestion: ShopifyCLI::Context.message("script.error.graphql_error_help"),
239
239
  }
240
+ when Layers::Infrastructure::Errors::InvalidEnvironmentError
241
+ {
242
+ cause_of_error: ShopifyCLI::Context.message(
243
+ "script.error.invalid_environment_cause",
244
+ tool: e.tool,
245
+ env_version: e.env_version,
246
+ minimum_version: e.minimum_version,
247
+ ),
248
+ help_suggestion: ShopifyCLI::Context.message(
249
+ "script.error.invalid_environment_help",
250
+ tool: e.tool,
251
+ ),
252
+ }
240
253
  when Layers::Infrastructure::Errors::SystemCallFailureError
241
254
  {
242
255
  cause_of_error: ShopifyCLI::Context
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Theme
4
+ class Command
5
+ module Common
6
+ module RootHelper
7
+ def root_value(options, name)
8
+ argv = default_argv(options)
9
+ command_index = argv.index(name.to_s)
10
+
11
+ return "." if command_index.nil?
12
+
13
+ next_index = command_index + 1
14
+ option_by_key = options_map(options)
15
+
16
+ while next_index < argv.size
17
+ element = argv[next_index]
18
+ option = option_by_key[element]
19
+
20
+ return element if option.nil?
21
+
22
+ # Skip the option argument
23
+ next_index += 1 unless option.arg.nil?
24
+
25
+ # PATTERN arguments take precedence over the `root`
26
+ if option.arg =~ /PATTERN/
27
+ next_index += 1 while option_argument?(argv, next_index, option_by_key)
28
+ next
29
+ end
30
+
31
+ next_index += 1
32
+ end
33
+
34
+ "."
35
+ end
36
+
37
+ private
38
+
39
+ def default_argv(options)
40
+ options.parser.default_argv
41
+ end
42
+
43
+ def options_map(options)
44
+ map = {}
45
+ options_list(options).each do |option|
46
+ map[option.short.first] = option
47
+ map[option.long.first] = option
48
+ end
49
+ map
50
+ end
51
+
52
+ def options_list(options)
53
+ options.parser.top.list
54
+ end
55
+
56
+ def option_argument?(argv, next_index, option_by_key)
57
+ return false unless next_index < argv.size
58
+
59
+ element = argv[next_index]
60
+ option_by_key[element].nil?
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -9,6 +9,8 @@ module Theme
9
9
  parser.on("-u", "--clone-url URL") { |url| flags[:clone_url] = url }
10
10
  end
11
11
 
12
+ prerequisite_task :ensure_git_dependency
13
+
12
14
  DEFAULT_CLONE_URL = "https://github.com/Shopify/dawn.git"
13
15
 
14
16
  def call(args, _name)
@@ -4,35 +4,43 @@ 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] << pattern
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] << pattern
33
+ flags[:ignores] += pattern
26
34
  end
27
35
  end
28
36
 
29
- def call(args, _name)
30
- root = args.first || "."
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
 
@@ -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", dev_theme.name))
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] << pattern
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] << pattern
37
+ flags[:ignores] += pattern
30
38
  end
31
39
  end
32
40
 
33
- def call(args, _name)
34
- root = args.first || "."
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,7 +50,7 @@ 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
 
@@ -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, ".", host: host, **flags) do |syncer|
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
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_glob"
4
+
5
+ module Theme
6
+ module Conversions
7
+ class IgnoreGlob < BaseGlob
8
+ class << self
9
+ def options
10
+ %w(-x --ignore)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base_glob"
4
+
5
+ module Theme
6
+ module Conversions
7
+ class IncludeGlob < BaseGlob
8
+ class << self
9
+ def options
10
+ %w(-o --only)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -65,8 +65,8 @@ module Theme
65
65
  {{command:-j, --json}} Output JSON instead of a UI.
66
66
  {{command:-a, --allow-live}} Allow push to a live theme.
67
67
  {{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.
68
+ {{command:-o, --only}} Upload only the specified files (Multiple flags allowed).
69
+ {{command:-x, --ignore}} Skip uploading the specified files (Multiple flags allowed).
70
70
 
71
71
  Run without options to select theme from a list.
72
72
  HELP
@@ -96,7 +96,7 @@ module Theme
96
96
  help: <<~HELP,
97
97
  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
98
 
99
- Usage: {{command:%s theme serve}}
99
+ Usage: {{command:%s theme serve [ ROOT ]}}
100
100
 
101
101
  Options:
102
102
  {{command:--port=PORT}} Local port to serve theme preview from.
@@ -202,8 +202,8 @@ module Theme
202
202
  {{command:-l, --live}} Pull theme files from your remote live theme.
203
203
  {{command:-d, --development}} Pull theme files from your remote development theme.
204
204
  {{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.
205
+ {{command:-o, --only}} Download only the specified files (Multiple flags allowed).
206
+ {{command:-x, --ignore}} Skip downloading the specified files (Multiple flags allowed).
207
207
 
208
208
  Run without options to select theme from a list.
209
209
  HELP
@@ -4,6 +4,7 @@ module ShopifyCLI
4
4
  class Create
5
5
  class Node < ShopifyCLI::Command::AppSubCommand
6
6
  prerequisite_task :ensure_authenticated
7
+ prerequisite_task :ensure_git_dependency
7
8
 
8
9
  recommend_default_node_range
9
10
  recommend_default_ruby_range
@@ -4,6 +4,7 @@ module ShopifyCLI
4
4
  class Create
5
5
  class PHP < ShopifyCLI::Command::AppSubCommand
6
6
  prerequisite_task :ensure_authenticated
7
+ prerequisite_task :ensure_git_dependency
7
8
 
8
9
  options do |parser, flags|
9
10
  parser.on("--name=NAME") { |name| flags[:name] = name }
@@ -4,6 +4,7 @@ module ShopifyCLI
4
4
  class Create
5
5
  class Rails < ShopifyCLI::Command::AppSubCommand
6
6
  prerequisite_task :ensure_authenticated
7
+ prerequisite_task :ensure_git_dependency
7
8
 
8
9
  recommend_default_ruby_range
9
10
  recommend_default_node_range
@@ -3,6 +3,7 @@ module ShopifyCLI
3
3
  class App
4
4
  class Deploy < ShopifyCLI::Command::AppSubCommand
5
5
  subcommand :Heroku, "heroku", "shopify_cli/commands/app/deploy/heroku"
6
+ prerequisite_task :ensure_git_dependency
6
7
 
7
8
  recommend_default_ruby_range
8
9
 
@@ -25,6 +25,12 @@ module ShopifyCLI
25
25
  ::Semantic::Version.new(out.chomp)
26
26
  end
27
27
 
28
+ def self.npm_version(context: Context.new)
29
+ out, err, stat = context.capture3("npm", "--version")
30
+ raise ShopifyCLI::Abort, err unless stat.success?
31
+ ::Semantic::Version.new(out.chomp)
32
+ end
33
+
28
34
  def self.interactive=(interactive)
29
35
  @interactive = interactive
30
36
  end
@@ -4,7 +4,15 @@ module ShopifyCLI
4
4
  # git.
5
5
  class Git
6
6
  class << self
7
- # Check if Git is available in the environment
7
+ # Check if Git exists in the environment
8
+ def exists?(ctx)
9
+ _output, status = ctx.capture2e("git", "version")
10
+ status.success?
11
+ rescue Errno::ENOENT # git is not installed
12
+ false
13
+ end
14
+
15
+ # Check if the current working directory is a Git repository
8
16
  def available?(ctx)
9
17
  _output, status = ctx.capture2e("git", "status")
10
18
  status.success?
@@ -277,6 +277,24 @@ module ShopifyCLI
277
277
  HELP
278
278
  },
279
279
  },
280
+ extension: {
281
+ push: {
282
+ checkout_ui_extension: {
283
+ localization: {
284
+ error: {
285
+ bundle_too_large: "Total size of all locale files must be less than %s.",
286
+ file_empty: "Locale file `%s` is empty.",
287
+ file_too_large: "Locale file `%s` too large; size must be less than %s.",
288
+ invalid_file_extension: "Invalid locale filename: `%s`; only .json files are allowed.",
289
+ invalid_locale_code: "Invalid locale filename: `%s`; locale code should be 2 or 3 letters,"\
290
+ " optionally followed by a two-letter region code, e.g. `fr-CA`.",
291
+ single_default_locale: "There must be one and only one locale identified as the default locale,"\
292
+ " e.g. `en.default.json`",
293
+ },
294
+ },
295
+ },
296
+ },
297
+ },
280
298
  error_reporting: {
281
299
  unhandled_error: {
282
300
  message: "{{x}} {{red:An unexpected error occured.}}",
@@ -355,6 +373,7 @@ module ShopifyCLI
355
373
  error: {
356
374
  directory_exists: "Project directory already exists. Please create a project with a new name.",
357
375
  no_branches_found: "Could not find any git branches",
376
+ nonexistent: "Git needs to be installed: https://git-scm.com/download",
358
377
  repo_not_initiated:
359
378
  "Git repo is not initiated. Please run {{command:git init}} and make at least one commit.",
360
379
  no_commits_made: "No git commits have been made. Please make at least one commit.",
@@ -672,7 +691,8 @@ module ShopifyCLI
672
691
  },
673
692
  },
674
693
  ensure_dev_store: {
675
- could_not_verify_store: "Couldn't verify your store %s",
694
+ could_not_verify_store: "Couldn't verify your store. If you don't have a development store set up, "\
695
+ "please create one in your Partners dashboard and run `shopify app connect`.",
676
696
  convert_to_dev_store: <<~MESSAGE,
677
697
  Do you want to convert %s to a development store?
678
698
  Doing this will allow you to install your app, but the store will become {{bold:transfer-disabled}}.
@@ -0,0 +1,14 @@
1
+ require "shopify_cli"
2
+
3
+ module ShopifyCLI
4
+ module Tasks
5
+ class EnsureGitDependency < ShopifyCLI::Task
6
+ def call(ctx)
7
+ return if ShopifyCLI::Environment.acceptance_test?
8
+ unless ShopifyCLI::Git.exists?(ctx)
9
+ raise ShopifyCLI::Abort, ctx.message("core.git.error.nonexistent")
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -34,6 +34,7 @@ module ShopifyCLI
34
34
  register :CreateApiClient, :create_api_client, "shopify_cli/tasks/create_api_client"
35
35
  register :EnsureAuthenticated, :ensure_authenticated, "shopify_cli/tasks/ensure_authenticated"
36
36
  register :EnsureEnv, :ensure_env, "shopify_cli/tasks/ensure_env"
37
+ register :EnsureGitDependency, :ensure_git_dependency, "shopify_cli/tasks/ensure_git_dependency"
37
38
  register :EnsureLoopbackURL, :ensure_loopback_url, "shopify_cli/tasks/ensure_loopback_url"
38
39
  register :EnsureProjectType, :ensure_project_type, "shopify_cli/tasks/ensure_project_type"
39
40
  register :EnsureDevStore, :ensure_dev_store, "shopify_cli/tasks/ensure_dev_store"
@@ -3,7 +3,6 @@ require "net/http"
3
3
  require "stringio"
4
4
  require "time"
5
5
  require "cgi"
6
-
7
6
  require_relative "proxy/template_param_builder"
8
7
 
9
8
  module ShopifyCLI
@@ -70,13 +69,26 @@ module ShopifyCLI
70
69
  @core_endpoints << env["PATH_INFO"]
71
70
  end
72
71
 
73
- body = response.body || [""]
72
+ body = patch_body(env, response.body)
74
73
  body = [body] unless body.respond_to?(:each)
75
74
  [response.code, headers, body]
76
75
  end
77
76
 
78
77
  private
79
78
 
79
+ def patch_body(env, body)
80
+ return [""] unless body
81
+
82
+ body.gsub(%r{(data-.+=(["']))(http:|https:)?//#{@theme.shop}(.*)(\2)}) do |_|
83
+ match = Regexp.last_match
84
+ "#{match[1]}http://#{host(env)}#{match[4]}#{match[5]}"
85
+ end
86
+ end
87
+
88
+ def host(env)
89
+ env["HTTP_HOST"]
90
+ end
91
+
80
92
  def has_body?(headers)
81
93
  headers["Content-Length"] || headers["Transfer-Encoding"]
82
94
  end
@@ -9,7 +9,8 @@ module ShopifyCLI
9
9
 
10
10
  attr_reader :globs, :regexes
11
11
 
12
- def initialize(patterns = [])
12
+ def initialize(root, patterns = [])
13
+ @root = Pathname.new(root)
13
14
  @patterns = patterns.nil? ? [] : patterns.compact.reject(&:empty?)
14
15
 
15
16
  regexes, globs = patterns_to_regexes_and_globs(@patterns)
@@ -22,9 +23,10 @@ module ShopifyCLI
22
23
  return true unless present?(@patterns)
23
24
 
24
25
  path = path.to_s
25
-
26
26
  return true if path.empty?
27
27
 
28
+ path = @root.join(path).to_s
29
+
28
30
  regexes.each do |regex|
29
31
  return true if regex_match?(regex, path)
30
32
  end