shopify-cli 2.10.1 → 2.11.2

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.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.yaml +117 -0
  3. data/.github/ISSUE_TEMPLATE/enhancement.yaml +38 -0
  4. data/.github/ISSUE_TEMPLATE/feature.yaml +47 -0
  5. data/.github/ISSUE_TEMPLATE.md +18 -0
  6. data/CHANGELOG.md +38 -3
  7. data/Gemfile.lock +1 -1
  8. data/bin/shopify +9 -0
  9. data/dev.yml +3 -0
  10. data/lib/project_types/extension/commands/check.rb +2 -0
  11. data/lib/project_types/extension/commands/create.rb +2 -0
  12. data/lib/project_types/extension/commands/push.rb +15 -0
  13. data/lib/project_types/extension/commands/serve.rb +2 -0
  14. data/lib/project_types/extension/loaders/project.rb +28 -8
  15. data/lib/project_types/extension/messages/messages.rb +10 -2
  16. data/lib/project_types/extension/models/specification_handlers/default.rb +1 -1
  17. data/lib/project_types/extension/models/specification_handlers/theme_app_extension.rb +7 -1
  18. data/lib/project_types/extension/tasks/convert_server_config.rb +3 -1
  19. data/lib/project_types/script/cli.rb +5 -0
  20. data/lib/project_types/script/commands/connect.rb +3 -1
  21. data/lib/project_types/script/commands/create.rb +2 -0
  22. data/lib/project_types/script/commands/push.rb +6 -0
  23. data/lib/project_types/script/config/extension_points.yml +12 -0
  24. data/lib/project_types/script/graphql/module_upload_url_generate.graphql +5 -1
  25. data/lib/project_types/script/layers/application/build_script.rb +6 -2
  26. data/lib/project_types/script/layers/application/create_script.rb +1 -1
  27. data/lib/project_types/script/layers/application/project_dependencies.rb +1 -1
  28. data/lib/project_types/script/layers/application/push_script.rb +39 -31
  29. data/lib/project_types/script/layers/domain/errors.rb +7 -1
  30. data/lib/project_types/script/layers/domain/extension_point.rb +2 -2
  31. data/lib/project_types/script/layers/infrastructure/errors.rb +13 -3
  32. data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_task_runner.rb +3 -16
  33. data/lib/project_types/script/layers/infrastructure/languages/project_creator.rb +1 -0
  34. data/lib/project_types/script/layers/infrastructure/languages/task_runner.rb +35 -8
  35. data/lib/project_types/script/layers/infrastructure/languages/typescript_task_runner.rb +3 -16
  36. data/lib/project_types/script/layers/infrastructure/languages/wasm_project_creator.rb +15 -0
  37. data/lib/project_types/script/layers/infrastructure/languages/wasm_task_runner.rb +32 -0
  38. data/lib/project_types/script/layers/infrastructure/metadata_repository.rb +18 -0
  39. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +1 -1
  40. data/lib/project_types/script/layers/infrastructure/script_service.rb +12 -8
  41. data/lib/project_types/script/layers/infrastructure/script_uploader.rb +22 -9
  42. data/lib/project_types/script/loaders/project.rb +2 -1
  43. data/lib/project_types/script/messages/messages.rb +92 -84
  44. data/lib/project_types/script/ui/error_handler.rb +39 -14
  45. data/lib/project_types/theme/commands/check.rb +2 -0
  46. data/lib/project_types/theme/commands/delete.rb +2 -0
  47. data/lib/project_types/theme/commands/init.rb +2 -0
  48. data/lib/project_types/theme/commands/language_server.rb +2 -0
  49. data/lib/project_types/theme/commands/package.rb +2 -0
  50. data/lib/project_types/theme/commands/publish.rb +2 -0
  51. data/lib/project_types/theme/commands/pull.rb +9 -2
  52. data/lib/project_types/theme/commands/push.rb +7 -4
  53. data/lib/project_types/theme/commands/serve.rb +2 -0
  54. data/lib/shopify_cli/command/sub_command.rb +2 -0
  55. data/lib/shopify_cli/command.rb +74 -0
  56. data/lib/shopify_cli/commands/app/create/node.rb +3 -0
  57. data/lib/shopify_cli/commands/app/create/rails.rb +3 -0
  58. data/lib/shopify_cli/commands/app/deploy.rb +2 -0
  59. data/lib/shopify_cli/commands/app/serve.rb +2 -0
  60. data/lib/shopify_cli/constants.rb +13 -1
  61. data/lib/shopify_cli/environment.rb +55 -35
  62. data/lib/shopify_cli/exception_reporter.rb +9 -0
  63. data/lib/shopify_cli/github/issue_url_generator.rb +19 -8
  64. data/lib/shopify_cli/identity_auth/env_auth_token.rb +34 -0
  65. data/lib/shopify_cli/identity_auth.rb +33 -15
  66. data/lib/shopify_cli/messages/messages.rb +3 -2
  67. data/lib/shopify_cli/partners_api.rb +7 -2
  68. data/lib/shopify_cli/services/app/create/rails_service.rb +37 -13
  69. data/lib/shopify_cli/theme/dev_server/hot_reload/remote_file_reloader.rb +63 -0
  70. data/lib/shopify_cli/theme/dev_server/hot_reload.rb +22 -6
  71. data/lib/shopify_cli/theme/dev_server/proxy.rb +4 -5
  72. data/lib/shopify_cli/theme/dev_server.rb +1 -3
  73. data/lib/shopify_cli/theme/development_theme.rb +11 -0
  74. data/lib/shopify_cli/theme/file.rb +4 -0
  75. data/lib/shopify_cli/theme/include_filter.rb +39 -17
  76. data/lib/shopify_cli/theme/theme.rb +0 -4
  77. data/lib/shopify_cli/utilities.rb +7 -0
  78. data/lib/shopify_cli/version.rb +1 -1
  79. data/lib/shopify_cli.rb +1 -0
  80. data/vendor/deps/cli-kit/lib/cli/kit/system.rb +11 -6
  81. data/vendor/deps/cli-kit/lib/cli/kit/util.rb +5 -1
  82. data/vendor/deps/cli-ui/lib/cli/ui/os.rb +6 -4
  83. data/vendor/lib/semantic/version.rb +0 -1
  84. metadata +11 -3
  85. data/lib/project_types/rails/commands/create.rb +0 -210
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "hot_reload/remote_file_reloader"
4
+
3
5
  module ShopifyCLI
4
6
  module Theme
5
7
  module DevServer
@@ -10,6 +12,7 @@ module ShopifyCLI
10
12
  @theme = theme
11
13
  @mode = mode
12
14
  @streams = SSE::Streams.new
15
+ @remote_file_reloader = RemoteFileReloader.new(ctx, theme: @theme, streams: @streams)
13
16
  @watcher = watcher
14
17
  @watcher.add_observer(self, :notify_streams_of_file_change)
15
18
  @ignore_filter = ignore_filter
@@ -32,17 +35,30 @@ module ShopifyCLI
32
35
  end
33
36
 
34
37
  def notify_streams_of_file_change(modified, added, _removed)
35
- files = (modified + added).reject { |file| @ignore_filter&.ignore?(file) }
36
- .map { |file| @theme[file].relative_path }
38
+ files = (modified + added)
39
+ .reject { |file| @ignore_filter&.ignore?(file) }
40
+ .map { |file| @theme[file] }
37
41
 
38
- unless files.empty?
39
- @streams.broadcast(JSON.generate(modified: files))
40
- @ctx.debug("[HotReload] Modified #{files.join(", ")}")
41
- end
42
+ files -= liquid_css_files = files.select(&:liquid_css?)
43
+
44
+ hot_reload(files) unless files.empty?
45
+ remote_reload(liquid_css_files)
42
46
  end
43
47
 
44
48
  private
45
49
 
50
+ def hot_reload(files)
51
+ paths = files.map(&:relative_path)
52
+ @streams.broadcast(JSON.generate(modified: paths))
53
+ @ctx.debug("[HotReload] Modified #{paths.join(", ")}")
54
+ end
55
+
56
+ def remote_reload(files)
57
+ files.each do |file|
58
+ @remote_file_reloader.reload(file)
59
+ end
60
+ end
61
+
46
62
  def request_is_html?(headers)
47
63
  headers["content-type"]&.start_with?("text/html")
48
64
  end
@@ -43,9 +43,8 @@ module ShopifyCLI
43
43
  headers["Accept-Encoding"] = "none"
44
44
  headers["User-Agent"] = "Shopify CLI"
45
45
 
46
- query = URI.decode_www_form(env["QUERY_STRING"]).to_h
46
+ query = URI.decode_www_form(env["QUERY_STRING"])
47
47
  replace_templates = build_replace_templates_param(env)
48
-
49
48
  response = if replace_templates.any?
50
49
  # Pass to SFR the recently modified templates in `replace_templates` body param
51
50
  headers["Authorization"] = "Bearer #{bearer_token}"
@@ -158,7 +157,7 @@ module ShopifyCLI
158
157
  def secure_session_id
159
158
  if secure_session_id_expired?
160
159
  @ctx.debug("Refreshing preview _secure_session_id cookie")
161
- response = request("HEAD", "/", query: { preview_theme_id: @theme.id })
160
+ response = request("HEAD", "/", query: [[:preview_theme_id, @theme.id]])
162
161
  @secure_session_id = extract_secure_session_id_from_response_headers(response)
163
162
  @last_session_cookie_refresh = Time.now
164
163
  end
@@ -189,9 +188,9 @@ module ShopifyCLI
189
188
  response_headers
190
189
  end
191
190
 
192
- def request(method, path, headers: nil, query: {}, form_data: nil, body_stream: nil)
191
+ def request(method, path, headers: nil, query: [], form_data: nil, body_stream: nil)
193
192
  uri = URI.join("https://#{@theme.shop}", path)
194
- uri.query = URI.encode_www_form(query.merge(_fd: 0, pb: 0))
193
+ uri.query = URI.encode_www_form(query + [[:_fd, 0], [:pb, 0]])
195
194
 
196
195
  @ctx.debug("Proxying #{method} #{uri}")
197
196
 
@@ -28,7 +28,7 @@ module ShopifyCLI
28
28
 
29
29
  def start(ctx, root, host: "127.0.0.1", port: 9292, poll: false, mode: ReloadMode.default)
30
30
  @ctx = ctx
31
- theme = DevelopmentTheme.new(ctx, root: root)
31
+ theme = DevelopmentTheme.find_or_create!(ctx, root: root)
32
32
  ignore_filter = IgnoreFilter.from_path(root)
33
33
  @syncer = Syncer.new(ctx, theme: theme, ignore_filter: ignore_filter)
34
34
  watcher = Watcher.new(ctx, theme: theme, syncer: @syncer, ignore_filter: ignore_filter, poll: poll)
@@ -41,8 +41,6 @@ module ShopifyCLI
41
41
  stopped = false
42
42
  address = "http://#{host}:#{port}"
43
43
 
44
- theme.ensure_exists!
45
-
46
44
  trap("INT") do
47
45
  stopped = true
48
46
  stop
@@ -38,6 +38,8 @@ module ShopifyCLI
38
38
  @ctx.debug("Created temporary development theme: #{@id}")
39
39
  ShopifyCLI::DB.set(development_theme_id: @id)
40
40
  end
41
+
42
+ self
41
43
  end
42
44
 
43
45
  def exists?
@@ -63,6 +65,15 @@ module ShopifyCLI
63
65
  new(ctx).delete
64
66
  end
65
67
 
68
+ def self.find(ctx, root: nil)
69
+ dev_theme = new(ctx, root: root)
70
+ dev_theme.exists? ? dev_theme : nil
71
+ end
72
+
73
+ def self.find_or_create!(ctx, root: nil)
74
+ new(ctx, root: root).ensure_exists!
75
+ end
76
+
66
77
  private
67
78
 
68
79
  def generate_theme_name
@@ -53,6 +53,10 @@ module ShopifyCLI
53
53
  path.extname == ".liquid"
54
54
  end
55
55
 
56
+ def liquid_css?
57
+ relative_path.to_s.end_with?(".css.liquid")
58
+ end
59
+
56
60
  def json?
57
61
  path.extname == ".json"
58
62
  end
@@ -7,36 +7,58 @@ module ShopifyCLI
7
7
  class IncludeFilter
8
8
  include Filter::PathMatcher
9
9
 
10
- def initialize(pattern = nil)
11
- @pattern = pattern
10
+ attr_reader :globs, :regexes
11
+
12
+ def initialize(patterns = [])
13
+ @patterns = patterns.nil? ? [] : patterns.compact.reject(&:empty?)
14
+
15
+ regexes, globs = patterns_to_regexes_and_globs(@patterns)
16
+
17
+ @regexes = regexes
18
+ @globs = globs
12
19
  end
13
20
 
14
21
  def match?(path)
15
- return true unless present?(@pattern)
22
+ return true unless present?(@patterns)
23
+
24
+ path = path.to_s
25
+
26
+ return true if path.empty?
16
27
 
17
- if regex_pattern?
18
- regex_match?(regex_pattern, path)
19
- else
20
- glob_match?(glob_pattern, path)
28
+ regexes.each do |regex|
29
+ return true if regex_match?(regex, path)
21
30
  end
31
+
32
+ globs.each do |glob|
33
+ return true if glob_match?(glob, path)
34
+ end
35
+
36
+ false
22
37
  end
23
38
 
24
39
  private
25
40
 
26
- def present?(pattern)
27
- !pattern.nil? && !pattern.empty?
41
+ def present?(patterns)
42
+ !patterns.nil? && !patterns.empty?
28
43
  end
29
44
 
30
- def regex_pattern?
31
- @is_regex_pattern ||= regex?(@pattern)
32
- end
45
+ # Take in string patterns and convert them to either
46
+ # regex patterns or glob patterns so that they are handled in an expected manner.
47
+ def patterns_to_regexes_and_globs(patterns)
48
+ new_regexes = []
49
+ new_globs = []
33
50
 
34
- def regex_pattern
35
- @regex_pattern ||= as_regex(@pattern)
36
- end
51
+ patterns
52
+ .map(&:strip)
53
+ .each do |pattern|
54
+ if regex?(pattern)
55
+ new_regexes << as_regex(pattern)
56
+ else
57
+ new_globs << as_glob(pattern)
58
+ end
59
+ end
37
60
 
38
- def glob_pattern
39
- @glob_pattern ||= as_glob(@pattern)
61
+ [new_regexes, new_globs]
40
62
  end
41
63
  end
42
64
  end
@@ -176,10 +176,6 @@ module ShopifyCLI
176
176
  find(ctx, root) { |attrs| attrs["role"] == "main" }
177
177
  end
178
178
 
179
- def development(ctx, root: nil)
180
- find(ctx, root) { |attrs| attrs["role"] == "development" }
181
- end
182
-
183
179
  # Finds a Theme by its identifier
184
180
  #
185
181
  # #### Parameters
@@ -0,0 +1,7 @@
1
+ module ShopifyCLI
2
+ module Utilities
3
+ def self.version_dropping_pre_and_build(version)
4
+ Semantic::Version.new("#{version.major}.#{version.minor}.#{version.patch}")
5
+ end
6
+ end
7
+ end
@@ -1,3 +1,3 @@
1
1
  module ShopifyCLI
2
- VERSION = "2.10.1"
2
+ VERSION = "2.11.2"
3
3
  end
data/lib/shopify_cli.rb CHANGED
@@ -136,6 +136,7 @@ module ShopifyCLI
136
136
  autoload :Tasks, "shopify_cli/tasks"
137
137
  autoload :TransformDataStructure, "shopify_cli/transform_data_structure"
138
138
  autoload :Tunnel, "shopify_cli/tunnel"
139
+ autoload :Utilities, "shopify_cli/utilities"
139
140
 
140
141
  require "shopify_cli/messages/messages"
141
142
  Context.load_messages(ShopifyCLI::Messages::MESSAGES)
@@ -174,11 +174,16 @@ module CLI
174
174
  end
175
175
 
176
176
  def os
177
- return :mac if /darwin/.match(RUBY_PLATFORM)
178
- return :linux if /linux/.match(RUBY_PLATFORM)
179
- return :windows if /mingw32/.match(RUBY_PLATFORM)
180
-
181
- raise "Could not determine OS from platform #{RUBY_PLATFORM}"
177
+ @current_os ||= case RbConfig::CONFIG['host_os']
178
+ when /darwin/ then :mac
179
+ when /linux/ then :linux
180
+ else
181
+ if RUBY_PLATFORM !~ /cygwin/ && ENV['OS'] == 'Windows_NT'
182
+ :windows
183
+ else
184
+ raise "Could not determine OS from host_os #{RbConfig::CONFIG["host_os"]}"
185
+ end
186
+ end
182
187
  end
183
188
 
184
189
  private
@@ -222,7 +227,7 @@ module CLI
222
227
  end
223
228
 
224
229
  def which(cmd, env)
225
- exts = os == :windows ? env.fetch('PATHEXT', ['']).split(';') : ['']
230
+ exts = (os == :windows && env['PATHEXT']&.split(';')) || ['']
226
231
  env.fetch('PATH', '').split(File::PATH_SEPARATOR).each do |path|
227
232
  exts.each do |ext|
228
233
  exe = File.join(path, "#{cmd}#{ext}")
@@ -168,9 +168,13 @@ module CLI
168
168
  @block_that_might_raise = block_that_might_raise
169
169
  end
170
170
 
171
- def retry_after(exception = StandardError, retries: 1, &before_retry)
171
+ def retry_after(exception = StandardError, retries: 1, only: nil, &before_retry)
172
172
  @block_that_might_raise.call
173
173
  rescue exception => e
174
+ should_retry = only ? only.call : true
175
+
176
+ raise unless should_retry
177
+
174
178
  raise if (retries -= 1) < 0
175
179
  if before_retry
176
180
  if before_retry.arity == 0
@@ -4,15 +4,17 @@ module CLI
4
4
  # Determines which OS is currently running the UI, to make it easier to
5
5
  # adapt its behaviour to the features of the OS.
6
6
  def self.current
7
- @current_os ||= case RUBY_PLATFORM
7
+ @current_os ||= case RbConfig::CONFIG['host_os']
8
8
  when /darwin/
9
9
  Mac
10
10
  when /linux/
11
11
  Linux
12
- when /mingw32/
13
- Windows
14
12
  else
15
- raise "Could not determine OS from platform #{RUBY_PLATFORM}"
13
+ if RUBY_PLATFORM !~ /cygwin/ && ENV['OS'] == 'Windows_NT'
14
+ Windows
15
+ else
16
+ raise "Could not determine OS from host_os #{RbConfig::CONFIG["host_os"]}"
17
+ end
16
18
  end
17
19
  end
18
20
 
@@ -21,7 +21,6 @@ module Semantic
21
21
  @version = version_str
22
22
  end
23
23
 
24
-
25
24
  def build=(b)
26
25
  @build = (!b.nil? && b.empty?) ? nil : b
27
26
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shopify-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.10.1
4
+ version: 2.11.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-28 00:00:00.000000000 Z
11
+ date: 2022-02-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -118,6 +118,9 @@ files:
118
118
  - ".github/CONTRIBUTING.md"
119
119
  - ".github/DESIGN.md"
120
120
  - ".github/ISSUE_TEMPLATE.md"
121
+ - ".github/ISSUE_TEMPLATE/bug_report.yaml"
122
+ - ".github/ISSUE_TEMPLATE/enhancement.yaml"
123
+ - ".github/ISSUE_TEMPLATE/feature.yaml"
121
124
  - ".github/PULL_REQUEST_TEMPLATE.md"
122
125
  - ".github/probots.yml"
123
126
  - ".github/workflows/shopify.yml"
@@ -273,7 +276,6 @@ files:
273
276
  - lib/project_types/php/forms/create.rb
274
277
  - lib/project_types/php/messages/messages.rb
275
278
  - lib/project_types/rails/cli.rb
276
- - lib/project_types/rails/commands/create.rb
277
279
  - lib/project_types/rails/forms/create.rb
278
280
  - lib/project_types/rails/gem.rb
279
281
  - lib/project_types/rails/messages/messages.rb
@@ -317,6 +319,9 @@ files:
317
319
  - lib/project_types/script/layers/infrastructure/languages/task_runner.rb
318
320
  - lib/project_types/script/layers/infrastructure/languages/typescript_project_creator.rb
319
321
  - lib/project_types/script/layers/infrastructure/languages/typescript_task_runner.rb
322
+ - lib/project_types/script/layers/infrastructure/languages/wasm_project_creator.rb
323
+ - lib/project_types/script/layers/infrastructure/languages/wasm_task_runner.rb
324
+ - lib/project_types/script/layers/infrastructure/metadata_repository.rb
320
325
  - lib/project_types/script/layers/infrastructure/push_package_repository.rb
321
326
  - lib/project_types/script/layers/infrastructure/script_project_repository.rb
322
327
  - lib/project_types/script/layers/infrastructure/script_service.rb
@@ -402,6 +407,7 @@ files:
402
407
  - lib/shopify_cli/heroku.rb
403
408
  - lib/shopify_cli/http_request.rb
404
409
  - lib/shopify_cli/identity_auth.rb
410
+ - lib/shopify_cli/identity_auth/env_auth_token.rb
405
411
  - lib/shopify_cli/identity_auth/servlet.rb
406
412
  - lib/shopify_cli/js_deps.rb
407
413
  - lib/shopify_cli/js_system.rb
@@ -463,6 +469,7 @@ files:
463
469
  - lib/shopify_cli/theme/dev_server/header_hash.rb
464
470
  - lib/shopify_cli/theme/dev_server/hot-reload.js
465
471
  - lib/shopify_cli/theme/dev_server/hot_reload.rb
472
+ - lib/shopify_cli/theme/dev_server/hot_reload/remote_file_reloader.rb
466
473
  - lib/shopify_cli/theme/dev_server/local_assets.rb
467
474
  - lib/shopify_cli/theme/dev_server/proxy.rb
468
475
  - lib/shopify_cli/theme/dev_server/proxy/template_param_builder.rb
@@ -485,6 +492,7 @@ files:
485
492
  - lib/shopify_cli/thread_pool/job.rb
486
493
  - lib/shopify_cli/transform_data_structure.rb
487
494
  - lib/shopify_cli/tunnel.rb
495
+ - lib/shopify_cli/utilities.rb
488
496
  - lib/shopify_cli/version.rb
489
497
  - shopify-cli.gemspec
490
498
  - shopify-dev
@@ -1,210 +0,0 @@
1
- # frozen_string_literal: true
2
- module Rails
3
- class Command
4
- class Create < ShopifyCLI::Command::AppSubCommand
5
- prerequisite_task :ensure_authenticated
6
-
7
- USER_AGENT_CODE = <<~USERAGENT
8
- module ShopifyAPI
9
- class Base < ActiveResource::Base
10
- self.headers['User-Agent'] << " | ShopifyApp/\#{ShopifyApp::VERSION} | Shopify CLI"
11
- end
12
- end
13
- USERAGENT
14
-
15
- DEFAULT_RAILS_FLAGS = %w(--skip-spring)
16
-
17
- options do |parser, flags|
18
- # backwards compatibility allow 'title' for now
19
- parser.on("--title=TITLE") { |t| flags[:title] = t }
20
- parser.on("--name=NAME") { |t| flags[:title] = t }
21
- parser.on("--organization_id=ID") { |id| flags[:organization_id] = id }
22
- parser.on("--organization-id=ID") { |id| flags[:organization_id] = id }
23
- parser.on("--store=MYSHOPIFYDOMAIN") { |url| flags[:shop_domain] = url }
24
- # backwards compatibility allow 'shop domain' for now
25
- parser.on("--shop_domain=MYSHOPIFYDOMAIN") { |url| flags[:shop_domain] = url }
26
- parser.on("--shop-domain=MYSHOPIFYDOMAIN") { |url| flags[:shop_domain] = url }
27
- parser.on("--type=APPTYPE") { |type| flags[:type] = type }
28
- parser.on("--db=DB") { |db| flags[:db] = db }
29
- parser.on("--rails_opts=RAILSOPTS") { |opts| flags[:rails_opts] = opts }
30
- parser.on("--rails-opts=RAILSOPTS") { |opts| flags[:rails_opts] = opts }
31
- end
32
-
33
- def call(args, _name)
34
- form_data = self.form_data(args)
35
- return @ctx.puts(self.class.help) if form_data.nil?
36
-
37
- ruby_version = Ruby.version(@ctx)
38
- @ctx.abort(@ctx.message("rails.create.error.invalid_ruby_version")) unless
39
- ruby_version.satisfies?("~>2.5") || ruby_version.satisfies?("~>3.0.0")
40
-
41
- check_node
42
- check_yarn
43
-
44
- build(form_data.name, form_data.db)
45
-
46
- set_custom_ua
47
- ShopifyCLI::Project.write(
48
- @ctx,
49
- project_type: "rails",
50
- organization_id: form_data.organization_id,
51
- )
52
-
53
- api_client = if ShopifyCLI::Environment.acceptance_test?
54
- {
55
- "apiKey" => "public_api_key",
56
- "apiSecretKeys" => [
57
- {
58
- "secret" => "api_secret_key",
59
- },
60
- ],
61
- }
62
- else
63
- ShopifyCLI::Tasks::CreateApiClient.call(
64
- @ctx,
65
- org_id: form_data.organization_id,
66
- title: form_data.title,
67
- type: form_data.type,
68
- )
69
- end
70
-
71
- ShopifyCLI::Resources::EnvFile.new(
72
- api_key: api_client["apiKey"],
73
- secret: api_client["apiSecretKeys"].first["secret"],
74
- shop: form_data.shop_domain,
75
- scopes: "write_products,write_customers,write_draft_orders",
76
- ).write(@ctx)
77
-
78
- partners_url = ShopifyCLI::PartnersAPI.partners_url_for(form_data.organization_id, api_client["id"])
79
-
80
- @ctx.puts(@ctx.message("apps.create.info.created", form_data.title, partners_url))
81
- @ctx.puts(@ctx.message("apps.create.info.serve", form_data.name, ShopifyCLI::TOOL_NAME, "rails"))
82
- unless ShopifyCLI::Shopifolk.acting_as_shopify_organization?
83
- @ctx.puts(@ctx.message("apps.create.info.install", partners_url, form_data.title))
84
- end
85
- end
86
-
87
- def form_data(args)
88
- if ShopifyCLI::Environment.acceptance_test?
89
- Struct.new(:title, :name, :organization_id, :type, :shop_domain, :db, keyword_init: true).new(
90
- title: options.flags[:title],
91
- name: options.flags[:title],
92
- organization_id: "123",
93
- shop_domain: "test.shopify.io",
94
- type: "public",
95
- db: options.flags[:db]
96
- )
97
- else
98
- Forms::Create.ask(@ctx, args, options.flags)
99
- end
100
- end
101
-
102
- def self.help
103
- ShopifyCLI::Context.message("rails.create.help", ShopifyCLI::TOOL_NAME, ShopifyCLI::TOOL_NAME)
104
- end
105
-
106
- private
107
-
108
- def check_node
109
- cmd_path = @ctx.which("node")
110
- if cmd_path.nil?
111
- @ctx.abort(@ctx.message("rails.create.error.node_required")) unless @ctx.windows?
112
- @ctx.puts("{{x}} {{red:" + @ctx.message("rails.create.error.node_required") + "}}")
113
- @ctx.puts(@ctx.message("rails.create.info.open_new_shell", "node"))
114
- raise ShopifyCLI::AbortSilent
115
- end
116
-
117
- version, stat = @ctx.capture2e("node", "-v")
118
- unless stat.success?
119
- @ctx.abort(@ctx.message("rails.create.error.node_version_failure")) unless @ctx.windows?
120
- # execution stops above if not Windows
121
- @ctx.puts("{{x}} {{red:" + @ctx.message("rails.create.error.node_version_failure") + "}}")
122
- @ctx.puts(@ctx.message("rails.create.info.open_new_shell", "node"))
123
- raise ShopifyCLI::AbortSilent
124
- end
125
-
126
- @ctx.done(@ctx.message("rails.create.node_version", version))
127
- end
128
-
129
- def check_yarn
130
- cmd_path = @ctx.which("yarn")
131
- if cmd_path.nil?
132
- @ctx.abort(@ctx.message("rails.create.error.yarn_required")) unless @ctx.windows?
133
- @ctx.puts("{{x}} {{red:" + @ctx.message("rails.create.error.yarn_required") + "}}")
134
- @ctx.puts(@ctx.message("rails.create.info.open_new_shell", "yarn"))
135
- raise ShopifyCLI::AbortSilent
136
- end
137
-
138
- version, stat = @ctx.capture2e("yarn", "-v")
139
- unless stat.success?
140
- @ctx.abort(@ctx.message("rails.create.error.yarn_version_failure")) unless @ctx.windows?
141
- @ctx.puts("{{x}} {{red:" + @ctx.message("rails.create.error.yarn_version_failure") + "}}")
142
- @ctx.puts(@ctx.message("rails.create.info.open_new_shell", "yarn"))
143
- raise ShopifyCLI::AbortSilent
144
- end
145
-
146
- @ctx.done(@ctx.message("rails.create.yarn_version", version))
147
- end
148
-
149
- def build(name, db)
150
- @ctx.abort(@ctx.message("rails.create.error.install_failure", "rails")) unless install_gem("rails", "<6.1")
151
- @ctx.abort(@ctx.message("rails.create.error.install_failure", "bundler ~>2.0")) unless
152
- install_gem("bundler", "~>2.0")
153
-
154
- full_path = File.join(@ctx.root, name)
155
- @ctx.abort(@ctx.message("rails.create.error.dir_exists", name)) if Dir.exist?(full_path)
156
-
157
- CLI::UI::Frame.open(@ctx.message("rails.create.generating_app", name)) do
158
- new_command = %w(rails new)
159
- new_command << name
160
- new_command += DEFAULT_RAILS_FLAGS
161
- new_command << "--database=#{db}"
162
- new_command += options.flags[:rails_opts].split unless options.flags[:rails_opts].nil?
163
-
164
- syscall(new_command)
165
- end
166
-
167
- @ctx.root = full_path
168
-
169
- File.open(File.join(@ctx.root, ".gitignore"), "a") { |f| f.write(".env") }
170
-
171
- @ctx.puts(@ctx.message("rails.create.adding_shopify_gem"))
172
- File.open(File.join(@ctx.root, "Gemfile"), "a") do |f|
173
- f.puts "\ngem 'shopify_app', '>=17.0.3'"
174
- end
175
- CLI::UI::Frame.open(@ctx.message("rails.create.running_bundle_install")) do
176
- syscall(%w(bundle install))
177
- end
178
-
179
- CLI::UI::Frame.open(@ctx.message("rails.create.running_generator")) do
180
- syscall(%w(rails generate shopify_app --new-shopify-cli-app))
181
- end
182
-
183
- CLI::UI::Frame.open(@ctx.message("rails.create.running_migrations")) do
184
- syscall(%w(rails db:create))
185
- syscall(%w(rails db:migrate RAILS_ENV=development))
186
- end
187
-
188
- unless File.exist?(File.join(@ctx.root, "config/webpacker.yml"))
189
- CLI::UI::Frame.open(@ctx.message("rails.create.running_webpacker_install")) do
190
- syscall(%w(rails webpacker:install))
191
- end
192
- end
193
- end
194
-
195
- def set_custom_ua
196
- ua_path = File.join("config", "initializers", "user_agent.rb")
197
- @ctx.write(ua_path, USER_AGENT_CODE)
198
- end
199
-
200
- def syscall(args)
201
- args[0] = Gem.binary_path_for(@ctx, args[0])
202
- @ctx.system(*args, chdir: @ctx.root)
203
- end
204
-
205
- def install_gem(name, version = nil)
206
- Gem.install(@ctx, name, version)
207
- end
208
- end
209
- end
210
- end