shopify-cli 2.6.4 → 2.7.1

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 (181) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer.json +5 -0
  3. data/.github/DESIGN.md +1 -1
  4. data/.github/ISSUE_TEMPLATE.md +7 -0
  5. data/.gitignore +1 -0
  6. data/.vscode/extensions.json +5 -0
  7. data/.vscode/settings.json +9 -0
  8. data/CHANGELOG.md +35 -3
  9. data/CONTRIBUTING.md +1 -21
  10. data/{Dockerfile → Codespace.dockerfile} +11 -3
  11. data/Gemfile +1 -0
  12. data/Gemfile.lock +6 -4
  13. data/README.md +20 -99
  14. data/Rakefile +27 -0
  15. data/Tests.dockerfile +35 -0
  16. data/assets/logo.png +0 -0
  17. data/dev.yml +0 -3
  18. data/docs/README.md +13 -0
  19. data/docs/contributors/testing.md +27 -0
  20. data/docs/users/installation.md +46 -0
  21. data/{THEMEKIT_MIGRATION.md → docs/users/migrate-from-themekit.md} +1 -1
  22. data/ext/javy/javy.rb +186 -0
  23. data/ext/javy/version +1 -0
  24. data/lib/project_types/extension/cli.rb +7 -3
  25. data/lib/project_types/extension/commands/build.rb +1 -0
  26. data/lib/project_types/extension/commands/create.rb +6 -6
  27. data/lib/project_types/extension/commands/extension_command.rb +1 -1
  28. data/lib/project_types/extension/features/argo.rb +1 -8
  29. data/lib/project_types/extension/features/argo_serve.rb +9 -23
  30. data/lib/project_types/extension/forms/create.rb +1 -1
  31. data/lib/project_types/extension/forms/questions/ask_template.rb +3 -6
  32. data/lib/project_types/extension/messages/messages.rb +1 -0
  33. data/lib/project_types/extension/models/development_server_requirements.rb +2 -3
  34. data/lib/project_types/extension/models/server_config/app.rb +13 -0
  35. data/lib/project_types/extension/models/server_config/development.rb +5 -4
  36. data/lib/project_types/extension/models/server_config/development_renderer.rb +1 -1
  37. data/lib/project_types/extension/models/server_config/development_resource.rb +13 -0
  38. data/lib/project_types/extension/models/server_config/extension.rb +4 -0
  39. data/lib/project_types/extension/models/server_config/root.rb +4 -1
  40. data/lib/project_types/extension/tasks/convert_server_config.rb +65 -0
  41. data/lib/project_types/extension/tasks/ensure_resource_url.rb +39 -0
  42. data/lib/project_types/extension/tasks/find_package_from_json.rb +37 -0
  43. data/lib/project_types/extension/tasks/merge_server_config.rb +32 -0
  44. data/lib/project_types/extension/tasks/run_extension_command.rb +11 -10
  45. data/lib/project_types/node/cli.rb +0 -16
  46. data/lib/project_types/node/forms/create.rb +5 -5
  47. data/lib/project_types/node/messages/messages.rb +2 -144
  48. data/lib/project_types/php/cli.rb +0 -11
  49. data/lib/project_types/php/forms/create.rb +5 -6
  50. data/lib/project_types/php/messages/messages.rb +2 -161
  51. data/lib/project_types/rails/cli.rb +0 -16
  52. data/lib/project_types/rails/commands/create.rb +46 -17
  53. data/lib/project_types/rails/forms/create.rb +5 -7
  54. data/lib/project_types/rails/messages/messages.rb +6 -151
  55. data/lib/project_types/script/cli.rb +2 -1
  56. data/lib/project_types/script/commands/create.rb +2 -5
  57. data/lib/project_types/script/commands/javy.rb +31 -0
  58. data/lib/project_types/script/commands/push.rb +1 -1
  59. data/lib/project_types/script/config/extension_points.yml +3 -0
  60. data/lib/project_types/script/errors.rb +0 -18
  61. data/lib/project_types/script/layers/application/create_script.rb +2 -2
  62. data/lib/project_types/script/layers/domain/script_json.rb +1 -1
  63. data/lib/project_types/script/layers/infrastructure/api_clients/partners_proxy_api_client.rb +0 -4
  64. data/lib/project_types/script/layers/infrastructure/errors.rb +8 -3
  65. data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_task_runner.rb +22 -3
  66. data/lib/project_types/script/layers/infrastructure/languages/typescript_task_runner.rb +25 -0
  67. data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +3 -4
  68. data/lib/project_types/script/layers/infrastructure/script_service.rb +1 -1
  69. data/lib/project_types/script/messages/messages.rb +16 -22
  70. data/lib/project_types/script/ui/error_handler.rb +1 -27
  71. data/lib/project_types/theme/cli.rb +1 -1
  72. data/lib/project_types/theme/commands/check.rb +1 -1
  73. data/lib/project_types/theme/commands/delete.rb +1 -1
  74. data/lib/project_types/theme/commands/init.rb +1 -1
  75. data/lib/project_types/theme/commands/language_server.rb +1 -1
  76. data/lib/project_types/theme/commands/package.rb +1 -1
  77. data/lib/project_types/theme/commands/publish.rb +1 -1
  78. data/lib/project_types/theme/commands/pull.rb +1 -1
  79. data/lib/project_types/theme/commands/push.rb +1 -1
  80. data/lib/project_types/theme/commands/serve.rb +9 -2
  81. data/lib/project_types/theme/messages/messages.rb +30 -1
  82. data/lib/shopify_cli/admin_api/populate_resource_command.rb +1 -1
  83. data/lib/shopify_cli/api.rb +7 -2
  84. data/lib/shopify_cli/app_type_detector.rb +24 -20
  85. data/lib/shopify_cli/command/app_sub_command.rb +10 -0
  86. data/lib/shopify_cli/command/project_command.rb +18 -0
  87. data/lib/shopify_cli/command/sub_command.rb +19 -0
  88. data/lib/shopify_cli/command.rb +7 -2
  89. data/lib/shopify_cli/commands/app/connect.rb +22 -0
  90. data/lib/shopify_cli/commands/app/create/node.rb +38 -0
  91. data/lib/shopify_cli/commands/app/create/php.rb +36 -0
  92. data/lib/shopify_cli/commands/app/create/rails.rb +40 -0
  93. data/lib/shopify_cli/commands/app/create.rb +28 -0
  94. data/lib/shopify_cli/commands/app/deploy.rb +49 -0
  95. data/lib/shopify_cli/commands/app/open.rb +19 -0
  96. data/lib/shopify_cli/commands/app/serve.rb +49 -0
  97. data/lib/shopify_cli/commands/app/tunnel.rb +43 -0
  98. data/lib/shopify_cli/commands/app.rb +29 -0
  99. data/lib/shopify_cli/commands/config.rb +2 -2
  100. data/lib/shopify_cli/commands.rb +1 -0
  101. data/lib/shopify_cli/constants.rb +4 -0
  102. data/lib/shopify_cli/exception_reporter.rb +8 -6
  103. data/lib/shopify_cli/git.rb +12 -1
  104. data/lib/shopify_cli/github/issue_url_generator.rb +19 -0
  105. data/lib/shopify_cli/github.rb +5 -0
  106. data/lib/shopify_cli/messages/messages.rb +253 -9
  107. data/lib/shopify_cli/migrator.rb +9 -11
  108. data/lib/shopify_cli/project.rb +5 -1
  109. data/lib/shopify_cli/project_commands.rb +1 -1
  110. data/lib/shopify_cli/services/app/connect_service.rb +25 -0
  111. data/lib/shopify_cli/services/app/create/node_service.rb +155 -0
  112. data/lib/shopify_cli/services/app/create/php_service.rb +152 -0
  113. data/lib/shopify_cli/services/app/create/rails_service.rb +215 -0
  114. data/lib/shopify_cli/services/app/deploy/heroku/node_service.rb +101 -0
  115. data/lib/shopify_cli/services/app/deploy/heroku/php_service.rb +135 -0
  116. data/lib/shopify_cli/services/app/deploy/heroku/rails_service.rb +120 -0
  117. data/lib/shopify_cli/services/app/open_service.rb +19 -0
  118. data/lib/shopify_cli/services/app/serve/node_service.rb +42 -0
  119. data/lib/shopify_cli/services/app/serve/php_service.rb +46 -0
  120. data/lib/shopify_cli/services/app/serve/rails_service.rb +48 -0
  121. data/lib/shopify_cli/services/app/tunnel/auth_service.rb +21 -0
  122. data/lib/shopify_cli/services/app/tunnel/start_service.rb +20 -0
  123. data/lib/shopify_cli/services/app/tunnel/stop_service.rb +20 -0
  124. data/lib/shopify_cli/services.rb +31 -0
  125. data/lib/shopify_cli/theme/dev_server/local_assets.rb +1 -1
  126. data/lib/shopify_cli/theme/dev_server.rb +35 -17
  127. data/lib/shopify_cli/tunnel.rb +25 -20
  128. data/lib/shopify_cli/version.rb +1 -1
  129. data/lib/shopify_cli.rb +1 -2
  130. data/shopify-cli.gemspec +2 -6
  131. data/shopify-dev +18 -0
  132. data/utilities/constants.rb +7 -0
  133. data/utilities/docker/container.rb +30 -2
  134. data/utilities/docker.rb +3 -2
  135. data/utilities/utilities.rb +1 -0
  136. data/vendor/deps/cli-kit/lib/cli/kit/system.rb +1 -1
  137. metadata +56 -53
  138. data/docs/_config.yml +0 -2
  139. data/docs/app/node/commands/index.md +0 -4
  140. data/docs/app/node/index.md +0 -4
  141. data/docs/app/rails/commands/index.md +0 -4
  142. data/docs/app/rails/index.md +0 -4
  143. data/docs/core/index.md +0 -4
  144. data/docs/getting-started/index.md +0 -4
  145. data/docs/getting-started/install/index.md +0 -4
  146. data/docs/getting-started/migrate/index.md +0 -4
  147. data/docs/getting-started/uninstall/index.md +0 -4
  148. data/docs/getting-started/upgrade/index.md +0 -4
  149. data/docs/help/start-app/index.md +0 -4
  150. data/docs/index.md +0 -4
  151. data/ext/shopify-cli/extconf.rb +0 -60
  152. data/install.sh +0 -7
  153. data/lib/project_types/extension/tasks/converters/server_config_converter.rb +0 -31
  154. data/lib/project_types/extension/tasks/load_server_config.rb +0 -23
  155. data/lib/project_types/node/commands/connect.rb +0 -21
  156. data/lib/project_types/node/commands/create.rb +0 -125
  157. data/lib/project_types/node/commands/deploy/heroku.rb +0 -96
  158. data/lib/project_types/node/commands/deploy.rb +0 -32
  159. data/lib/project_types/node/commands/generate.rb +0 -22
  160. data/lib/project_types/node/commands/open.rb +0 -18
  161. data/lib/project_types/node/commands/serve.rb +0 -45
  162. data/lib/project_types/node/commands/tunnel.rb +0 -41
  163. data/lib/project_types/php/commands/connect.rb +0 -19
  164. data/lib/project_types/php/commands/create.rb +0 -143
  165. data/lib/project_types/php/commands/deploy/heroku.rb +0 -129
  166. data/lib/project_types/php/commands/deploy.rb +0 -32
  167. data/lib/project_types/php/commands/open.rb +0 -16
  168. data/lib/project_types/php/commands/serve.rb +0 -48
  169. data/lib/project_types/php/commands/tunnel.rb +0 -37
  170. data/lib/project_types/rails/commands/connect.rb +0 -21
  171. data/lib/project_types/rails/commands/deploy/heroku.rb +0 -115
  172. data/lib/project_types/rails/commands/deploy.rb +0 -32
  173. data/lib/project_types/rails/commands/generate/webhook.rb +0 -42
  174. data/lib/project_types/rails/commands/generate.rb +0 -60
  175. data/lib/project_types/rails/commands/open.rb +0 -18
  176. data/lib/project_types/rails/commands/serve.rb +0 -51
  177. data/lib/project_types/rails/commands/tunnel.rb +0 -41
  178. data/lib/project_types/script/graphql/app_script_update_or_create.graphql +0 -0
  179. data/lib/shopify_cli/sub_command.rb +0 -17
  180. data/shopify.fish +0 -12
  181. data/shopify.sh +0 -11
@@ -44,15 +44,6 @@ module Script
44
44
  cause_of_error: ShopifyCLI::Context.message("script.error.invalid_context_cause"),
45
45
  help_suggestion: ShopifyCLI::Context.message("script.error.invalid_context_help"),
46
46
  }
47
- when Errors::InvalidConfigProps
48
- {
49
- cause_of_error: ShopifyCLI::Context.message("script.error.invalid_config_props_cause"),
50
- help_suggestion: ShopifyCLI::Context.message("script.error.invalid_config_props_help"),
51
- }
52
- when Errors::InvalidConfigYAMLError
53
- {
54
- cause_of_error: ShopifyCLI::Context.message("script.error.invalid_config", e.config_file),
55
- }
56
47
  when Layers::Infrastructure::Errors::InvalidLanguageError
57
48
  {
58
49
  cause_of_error: ShopifyCLI::Context.message("script.error.invalid_language_cause", e.language),
@@ -76,14 +67,6 @@ module Script
76
67
  cause_of_error: ShopifyCLI::Context.message("script.error.no_existing_orgs_cause"),
77
68
  help_suggestion: ShopifyCLI::Context.message("script.error.no_existing_orgs_help"),
78
69
  }
79
- when Errors::NoExistingStoresError
80
- {
81
- cause_of_error: ShopifyCLI::Context.message("script.error.no_existing_stores_cause"),
82
- help_suggestion: ShopifyCLI::Context.message(
83
- "script.error.no_existing_stores_help",
84
- organization_id: e.organization_id
85
- ),
86
- }
87
70
  when Layers::Infrastructure::Errors::ScriptProjectAlreadyExistsError
88
71
  {
89
72
  cause_of_error: ShopifyCLI::Context.message("script.error.project_exists_cause"),
@@ -91,7 +74,7 @@ module Script
91
74
  }
92
75
  when Layers::Infrastructure::Errors::DeprecatedEPError
93
76
  {
94
- cause_of_error: ShopifyCLI::Context.message("script.error.deprecated_ep", e.ep),
77
+ cause_of_error: ShopifyCLI::Context.message("script.error.deprecated_ep", e.extension_point),
95
78
  help_suggestion: ShopifyCLI::Context.message("script.error.deprecated_ep_cause"),
96
79
  }
97
80
  when Layers::Domain::Errors::InvalidExtensionPointError
@@ -135,10 +118,6 @@ module Script
135
118
  cause_of_error: ShopifyCLI::Context.message("script.error.no_script_json_file_cause"),
136
119
  help_suggestion: ShopifyCLI::Context.message("script.error.no_script_json_file_help"),
137
120
  }
138
- when Layers::Infrastructure::Errors::AppNotInstalledError
139
- {
140
- cause_of_error: ShopifyCLI::Context.message("script.error.app_not_installed_cause"),
141
- }
142
121
  when Layers::Infrastructure::Errors::BuildError
143
122
  {
144
123
  cause_of_error: ShopifyCLI::Context.message("script.error.build_error_cause"),
@@ -217,11 +196,6 @@ module Script
217
196
  cause_of_error: ShopifyCLI::Context.message("script.error.script_repush_cause"),
218
197
  help_suggestion: ShopifyCLI::Context.message("script.error.script_repush_help"),
219
198
  }
220
- when Layers::Infrastructure::Errors::ShopAuthenticationError
221
- {
222
- cause_of_error: ShopifyCLI::Context.message("script.error.shop_auth_cause"),
223
- help_suggestion: ShopifyCLI::Context.message("script.error.shop_auth_help"),
224
- }
225
199
  when Layers::Infrastructure::Errors::BuildScriptNotFoundError
226
200
  {
227
201
  cause_of_error: ShopifyCLI::Context.message("script.error.build_script_not_found"),
@@ -5,7 +5,7 @@ module Theme
5
5
  register_messages(Theme::Messages::MESSAGES)
6
6
  end
7
7
 
8
- class Command < ShopifyCLI::ProjectCommands
8
+ class Command < ShopifyCLI::Command::ProjectCommand
9
9
  subcommand :Init, "init", Project.project_filepath("commands/init")
10
10
  subcommand :Serve, "serve", Project.project_filepath("commands/serve")
11
11
  subcommand :Pull, "pull", Project.project_filepath("commands/pull")
@@ -3,7 +3,7 @@ require "theme_check"
3
3
 
4
4
  module Theme
5
5
  class Command
6
- class Check < ShopifyCLI::SubCommand
6
+ class Check < ShopifyCLI::Command::SubCommand
7
7
  class Options < ShopifyCLI::Options
8
8
  def initialize(theme_check)
9
9
  super()
@@ -4,7 +4,7 @@ require "shopify_cli/theme/development_theme"
4
4
 
5
5
  module Theme
6
6
  class Command
7
- class Delete < ShopifyCLI::SubCommand
7
+ class Delete < ShopifyCLI::Command::SubCommand
8
8
  options do |parser, flags|
9
9
  parser.on("-d", "--development") { flags[:development] = true }
10
10
  parser.on("-a", "--show-all") { flags[:show_all] = true }
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Theme
4
4
  class Command
5
- class Init < ShopifyCLI::SubCommand
5
+ class Init < ShopifyCLI::Command::SubCommand
6
6
  options do |parser, flags|
7
7
  parser.on("-u", "--clone-url URL") { |url| flags[:clone_url] = url }
8
8
  end
@@ -3,7 +3,7 @@ require "theme_check"
3
3
 
4
4
  module Theme
5
5
  class Command
6
- class LanguageServer < ShopifyCLI::SubCommand
6
+ class LanguageServer < ShopifyCLI::Command::SubCommand
7
7
  def call(*)
8
8
  ThemeCheck::LanguageServer.start
9
9
  end
@@ -4,7 +4,7 @@ require "json"
4
4
 
5
5
  module Theme
6
6
  class Command
7
- class Package < ShopifyCLI::SubCommand
7
+ class Package < ShopifyCLI::Command::SubCommand
8
8
  THEME_DIRECTORIES = %w[
9
9
  assets
10
10
  config
@@ -3,7 +3,7 @@ require "shopify_cli/theme/theme"
3
3
 
4
4
  module Theme
5
5
  class Command
6
- class Publish < ShopifyCLI::SubCommand
6
+ class Publish < ShopifyCLI::Command::SubCommand
7
7
  options do |parser, flags|
8
8
  parser.on("-f", "--force") { flags[:force] = true }
9
9
  end
@@ -5,7 +5,7 @@ require "shopify_cli/theme/syncer"
5
5
 
6
6
  module Theme
7
7
  class Command
8
- class Pull < ShopifyCLI::SubCommand
8
+ class Pull < ShopifyCLI::Command::SubCommand
9
9
  options do |parser, flags|
10
10
  parser.on("-n", "--nodelete") { flags[:nodelete] = true }
11
11
  parser.on("-i", "--themeid=ID") { |theme_id| flags[:theme_id] = theme_id }
@@ -6,7 +6,7 @@ require "shopify_cli/theme/syncer"
6
6
 
7
7
  module Theme
8
8
  class Command
9
- class Push < ShopifyCLI::SubCommand
9
+ class Push < ShopifyCLI::Command::SubCommand
10
10
  options do |parser, flags|
11
11
  parser.on("-n", "--nodelete") { flags[:nodelete] = true }
12
12
  parser.on("-i", "--themeid=ID") { |theme_id| flags[:theme_id] = theme_id }
@@ -3,17 +3,24 @@ require "shopify_cli/theme/dev_server"
3
3
 
4
4
  module Theme
5
5
  class Command
6
- class Serve < ShopifyCLI::SubCommand
6
+ class Serve < ShopifyCLI::Command::SubCommand
7
+ DEFAULT_HTTP_HOST = "127.0.0.1"
8
+
7
9
  options do |parser, flags|
10
+ parser.on("--host=HOST") { |host| flags[:host] = host.to_s }
8
11
  parser.on("--port=PORT") { |port| flags[:port] = port.to_i }
9
12
  parser.on("--poll") { flags[:poll] = true }
10
13
  end
11
14
 
12
15
  def call(*)
13
16
  flags = options.flags.dup
14
- ShopifyCLI::Theme::DevServer.start(@ctx, ".", **flags) do |syncer|
17
+ host = flags[:host] || DEFAULT_HTTP_HOST
18
+ ShopifyCLI::Theme::DevServer.start(@ctx, ".", http_bind: host, **flags) do |syncer|
15
19
  UI::SyncProgressBar.new(syncer).progress(:upload_theme!, delay_low_priority_files: true)
16
20
  end
21
+ rescue ShopifyCLI::Theme::DevServer::AddressBindingError
22
+ raise ShopifyCLI::Abort,
23
+ ShopifyCLI::Context.message("theme.serve.error.address_binding_error", ShopifyCLI::TOOL_NAME)
17
24
  end
18
25
 
19
26
  def self.help
@@ -94,9 +94,38 @@ module Theme
94
94
  Options:
95
95
  {{command:--port=PORT}} Local port to serve theme preview from
96
96
  {{command:--poll}} Force polling to detect file changes
97
+ {{command:--host=HOST}} Set which network interface the web server listens on. The default value is 127.0.0.1.
97
98
  HELP
98
- serve: "Viewing theme…",
99
+ viewing_theme: "Viewing theme…",
100
+ syncing_theme: "Syncing theme #%s on %s",
99
101
  open_fail: "Couldn't open the theme",
102
+ error: {
103
+ address_binding_error: "Couldn't bind to localhost."\
104
+ " To serve your theme, set a different address with {{command:%s theme serve --host=<address>}}",
105
+ },
106
+ serving: <<~SERVING,
107
+
108
+ Serving %s
109
+
110
+ SERVING
111
+ customize_or_preview: <<~CUSTOMIZE_OR_PREVIEW,
112
+
113
+ Customize this theme in the Online Store Editor:
114
+ {{green:%s}}
115
+
116
+ Share this theme preview:
117
+ {{green:%s}}
118
+
119
+ (Use Ctrl-C to stop)
120
+ CUSTOMIZE_OR_PREVIEW
121
+ ensure_user: <<~ENSURE_USER,
122
+ You are not authorized to edit themes on %s.
123
+ Make sure you are a user of that store, and allowed to edit themes.
124
+ ENSURE_USER
125
+ already_in_use_error: "Error",
126
+ address_already_in_use: "The address \"%s\" is already in use.",
127
+ try_this: "Try this",
128
+ try_port_option: "Use the --port=PORT option to serve the theme in a different port.",
100
129
  },
101
130
  check: {
102
131
  help: <<~HELP,
@@ -3,7 +3,7 @@ require "optparse"
3
3
 
4
4
  module ShopifyCLI
5
5
  class AdminAPI
6
- class PopulateResourceCommand < ShopifyCLI::SubCommand
6
+ class PopulateResourceCommand < ShopifyCLI::Command::SubCommand
7
7
  DEFAULT_COUNT = 5
8
8
 
9
9
  attr_reader :input
@@ -108,9 +108,14 @@ module ShopifyCLI
108
108
  private
109
109
 
110
110
  def default_headers
111
+ sha = ShopifyCLI.sha
112
+ user_agent = "Shopify CLI; v=#{ShopifyCLI::VERSION}"
113
+ sec_ch_ua = user_agent
114
+ sec_ch_ua += " sha=#{sha}" unless sha.nil?
115
+
111
116
  {
112
- "User-Agent" => "Shopify CLI; v=#{ShopifyCLI::VERSION}",
113
- "Sec-CH-UA" => "Shopify CLI; v=#{ShopifyCLI::VERSION} sha=#{ShopifyCLI.sha}",
117
+ "User-Agent" => user_agent,
118
+ "Sec-CH-UA" => sec_ch_ua,
114
119
  "Sec-CH-UA-PLATFORM" => ctx.os.to_s,
115
120
  "X-Request-Id" => SecureRandom.uuid,
116
121
  }.tap do |headers|
@@ -3,30 +3,34 @@ require "json"
3
3
  module ShopifyCLI
4
4
  class AppTypeDetector
5
5
  Error = Class.new(StandardError)
6
+ MissingShopifyCLIYamlError = Class.new(Error)
6
7
  TypeNotFoundError = Class.new(Error)
7
-
8
- def self.detect(project_directory:)
9
- return :node if node?(project_directory: project_directory)
10
- return :rails if rails?(project_directory: project_directory)
11
- return :php if php?(project_directory: project_directory)
12
- raise TypeNotFoundError, "Couldn't detect the project type in directory: #{project_directory}"
13
- end
14
-
15
- def self.node?(project_directory:)
16
- package_json_path = File.join(project_directory, "package.json")
17
- return false unless File.exist?(package_json_path)
18
- package_json = JSON.parse(File.read(package_json_path))
19
- !package_json.dig("scripts", "dev").nil?
8
+ class InvalidTypeError < Error
9
+ attr_reader :project_type
10
+ def initialize(message, project_type:)
11
+ @project_type = project_type
12
+ super(message)
13
+ end
20
14
  end
21
15
 
22
- def self.rails?(project_directory:)
23
- rails_binstub_path = File.join(project_directory, "bin/rails")
24
- File.exist?(rails_binstub_path)
25
- end
16
+ def self.detect(project_directory:)
17
+ require "yaml" # takes 20ms, so deferred as late as possible.
26
18
 
27
- def self.php?(project_directory:)
28
- bootstrap_app_path = File.join(project_directory, "bootstrap/app.php")
29
- File.exist?(bootstrap_app_path)
19
+ shopify_cli_yml_path = File.join(project_directory, Constants::Files::SHOPIFY_CLI_YML)
20
+ unless File.exist?(shopify_cli_yml_path)
21
+ raise MissingShopifyCLIYamlError,
22
+ "#{Constants::Files::SHOPIFY_CLI_YML} was not found in directory #{project_directory}"
23
+ end
24
+ shopify_cli = YAML.load_file(shopify_cli_yml_path)
25
+ case shopify_cli["project_type"]&.to_sym
26
+ when :node, :rails, :php
27
+ shopify_cli["project_type"].to_sym
28
+ when nil
29
+ raise TypeNotFoundError, "Couldn't detect the project type in directory: #{project_directory}"
30
+ else
31
+ raise InvalidTypeError.new("The project found '' is not supported",
32
+ project_type: shopify_cli["project_type"])
33
+ end
30
34
  end
31
35
  end
32
36
  end
@@ -1,6 +1,16 @@
1
1
  module ShopifyCLI
2
2
  class Command
3
3
  class AppSubCommand < SubCommand
4
+ def detect_app(directory: Dir.pwd)
5
+ AppTypeDetector.detect(project_directory: directory)
6
+ rescue ShopifyCLI::AppTypeDetector::TypeNotFoundError
7
+ raise ShopifyCLI::Abort, @ctx.message("core.app.error.type_not_found", directory)
8
+ rescue ShopifyCLI::AppTypeDetector::MissingShopifyCLIYamlError
9
+ raise ShopifyCLI::Abort, @ctx.message("core.app.error.missing_shopify_cli_yml", directory)
10
+ rescue ShopifyCLI::AppTypeDetector::InvalidTypeError => error
11
+ raise ShopifyCLI::Abort, @ctx.message("core.app.error.invalid_project_type", error.project_type)
12
+ end
13
+
4
14
  class << self
5
15
  def call_help(*)
6
16
  output = help
@@ -0,0 +1,18 @@
1
+ module ShopifyCLI
2
+ class Command
3
+ class ProjectCommand < Command
4
+ def call(*)
5
+ @ctx.puts(self.class.help)
6
+ end
7
+
8
+ def self.help
9
+ project_type = name.split("::")[0].downcase
10
+ ShopifyCLI::Context.message(
11
+ "#{project_type}.help",
12
+ ShopifyCLI::TOOL_NAME,
13
+ subcommand_registry.command_names.join(" | ")
14
+ )
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+ require "shopify_cli"
3
+
4
+ module ShopifyCLI
5
+ class Command
6
+ class SubCommand < Command
7
+ class << self
8
+ def call(args, command_name, parent_command)
9
+ cmd = new(@ctx)
10
+ args = cmd.options.parse(@_options, args || [])
11
+ return call_help(parent_command, command_name) if cmd.options.help
12
+ run_prerequisites
13
+
14
+ cmd.call(args, command_name)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -3,6 +3,10 @@ require "shopify_cli"
3
3
 
4
4
  module ShopifyCLI
5
5
  class Command < CLI::Kit::BaseCommand
6
+ autoload :SubCommand, "shopify_cli/command/sub_command"
7
+ autoload :AppSubCommand, "shopify_cli/command/app_sub_command"
8
+ autoload :ProjectCommand, "shopify_cli/command/project_command"
9
+
6
10
  extend Feature::Set
7
11
 
8
12
  attr_writer :ctx
@@ -11,12 +15,13 @@ module ShopifyCLI
11
15
  class << self
12
16
  attr_writer :ctx, :task_registry
13
17
 
14
- def call(args, command_name)
18
+ def call(args, command_name, *)
15
19
  subcommand, resolved_name = subcommand_registry.lookup_command(args.first)
16
20
  if subcommand
17
21
  subcommand.ctx = @ctx
18
22
  subcommand.task_registry = @task_registry
19
- subcommand.call(args, resolved_name, command_name)
23
+
24
+ subcommand.call(args.drop(1), resolved_name, command_name)
20
25
  else
21
26
  cmd = new(@ctx)
22
27
  cmd.options.parse(@_options, args)
@@ -0,0 +1,22 @@
1
+ module ShopifyCLI
2
+ module Commands
3
+ class App
4
+ class Connect < ShopifyCLI::Command::AppSubCommand
5
+ def call(_args, _command_name, *)
6
+ app_type = detect_app(directory: Dir.pwd)
7
+ project = ShopifyCLI::Project.current
8
+
9
+ Services::App::ConnectService.call(
10
+ app_type: app_type,
11
+ project: project,
12
+ context: @ctx
13
+ )
14
+ end
15
+
16
+ def self.help
17
+ ShopifyCLI::Context.message("core.app.connect.help", ShopifyCLI::TOOL_NAME, ShopifyCLI::TOOL_NAME)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,38 @@
1
+ module ShopifyCLI
2
+ module Commands
3
+ class App
4
+ class Create
5
+ class Node < ShopifyCLI::Command::AppSubCommand
6
+ unless ShopifyCLI::Environment.acceptance_test?
7
+ prerequisite_task :ensure_authenticated
8
+ end
9
+
10
+ options do |parser, flags|
11
+ parser.on("--name=NAME") { |t| flags[:name] = t }
12
+ parser.on("--organization-id=ID") { |id| flags[:organization_id] = id }
13
+ parser.on("--store-domain=MYSHOPIFYDOMAIN") { |url| flags[:store_domain] = url }
14
+ parser.on("--type=APPTYPE") { |type| flags[:type] = type }
15
+ parser.on("--verbose") { flags[:verbose] = true }
16
+ end
17
+
18
+ def call(*)
19
+ Services::App::Create::NodeService.call(
20
+ name: options.flags[:name],
21
+ organization_id: options.flags[:organization_id],
22
+ store_domain: options.flags[:store_domain],
23
+ type: options.flags[:type],
24
+ verbose: !options.flags[:verbose].nil?,
25
+ context: @ctx
26
+ )
27
+ end
28
+
29
+ class << self
30
+ def help
31
+ ShopifyCLI::Context.message("core.app.create.node.help", ShopifyCLI::TOOL_NAME, ShopifyCLI::TOOL_NAME)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,36 @@
1
+ module ShopifyCLI
2
+ module Commands
3
+ class App
4
+ class Create
5
+ class PHP < ShopifyCLI::Command::AppSubCommand
6
+ prerequisite_task :ensure_authenticated
7
+
8
+ options do |parser, flags|
9
+ parser.on("--name=NAME") { |name| flags[:name] = name }
10
+ parser.on("--organization-id=ID") { |organization_id| flags[:organization_id] = organization_id }
11
+ parser.on("--store-domain=MYSHOPIFYDOMAIN") { |url| flags[:store_domain] = url }
12
+ parser.on("--type=APPTYPE") { |type| flags[:type] = type }
13
+ parser.on("--verbose") { flags[:verbose] = true }
14
+ end
15
+
16
+ def call(*)
17
+ Services::App::Create::PHPService.call(
18
+ name: options.flags[:name],
19
+ organization_id: options.flags[:organization_id],
20
+ store_domain: options.flags[:store_domain],
21
+ type: options.flags[:type],
22
+ verbose: !options.flags[:verbose].nil?,
23
+ context: @ctx
24
+ )
25
+ end
26
+
27
+ class << self
28
+ def help
29
+ ShopifyCLI::Context.message("core.app.create.php.help", ShopifyCLI::TOOL_NAME, ShopifyCLI::TOOL_NAME)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,40 @@
1
+ module ShopifyCLI
2
+ module Commands
3
+ class App
4
+ class Create
5
+ class Rails < ShopifyCLI::Command::AppSubCommand
6
+ unless ShopifyCLI::Environment.acceptance_test?
7
+ prerequisite_task :ensure_authenticated
8
+ end
9
+
10
+ options do |parser, flags|
11
+ parser.on("--name=NAME") { |t| flags[:name] = t }
12
+ parser.on("--organization-id=ID") { |id| flags[:organization_id] = id }
13
+ parser.on("--store-domain=MYSHOPIFYDOMAIN") { |url| flags[:store_domain] = url }
14
+ parser.on("--type=APPTYPE") { |type| flags[:type] = type }
15
+ parser.on("--db=DB") { |db| flags[:db] = db }
16
+ parser.on("--rails-opts=RAILSOPTS") { |opts| flags[:rails_opts] = opts }
17
+ end
18
+
19
+ def call(*)
20
+ Services::App::Create::RailsService.call(
21
+ name: options.flags[:name],
22
+ organization_id: options.flags[:organization_id],
23
+ store_domain: options.flags[:store_domain],
24
+ type: options.flags[:type],
25
+ db: options.flags[:db],
26
+ rails_opts: options.flags[:rails_opts],
27
+ context: @ctx
28
+ )
29
+ end
30
+
31
+ class << self
32
+ def help
33
+ ShopifyCLI::Context.message("core.app.create.rails.help", ShopifyCLI::TOOL_NAME, ShopifyCLI::TOOL_NAME)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,28 @@
1
+ module ShopifyCLI
2
+ module Commands
3
+ class App
4
+ class Create < ShopifyCLI::Command
5
+ subcommand :Rails, "rails", "shopify_cli/commands/app/create/rails"
6
+ subcommand :PHP, "php", "shopify_cli/commands/app/create/php"
7
+ subcommand :Node, "node", "shopify_cli/commands/app/create/node"
8
+
9
+ def call(_args, _command_name)
10
+ @ctx.puts(self.class.help)
11
+ end
12
+
13
+ def self.help
14
+ ShopifyCLI::Context.message("core.app.create.help", ShopifyCLI::TOOL_NAME, ShopifyCLI::TOOL_NAME)
15
+ end
16
+
17
+ def self.call_help(*)
18
+ output = help
19
+ if respond_to?(:extended_help)
20
+ output += "\n"
21
+ output += extended_help
22
+ end
23
+ @ctx.puts(output)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,49 @@
1
+ module ShopifyCLI
2
+ module Commands
3
+ class App
4
+ class Deploy < ShopifyCLI::Command::AppSubCommand
5
+ subcommand :Heroku, "heroku", "shopify_cli/commands/app/deploy/heroku"
6
+
7
+ def call(args, _name)
8
+ platform = args.shift
9
+ case platform
10
+ when "heroku"
11
+ case detect_app
12
+ when :rails
13
+ Services::App::Deploy::Heroku::RailsService.call(
14
+ context: @ctx
15
+ )
16
+ when :php
17
+ Services::App::Deploy::Heroku::PHPService.call(
18
+ context: @ctx
19
+ )
20
+ when :node
21
+ Services::App::Deploy::Heroku::NodeService.call(
22
+ context: @ctx
23
+ )
24
+ end
25
+ when nil
26
+ raise ShopifyCLI::Abort, @ctx.message(
27
+ "core.app.deploy.error.missing_platform",
28
+ ShopifyCLI::TOOL_NAME
29
+ )
30
+ else
31
+ raise ShopifyCLI::Abort, @ctx.message(
32
+ "core.app.deploy.error.invalid_platform",
33
+ platform,
34
+ ShopifyCLI::TOOL_NAME
35
+ )
36
+ end
37
+ end
38
+
39
+ def self.help
40
+ ShopifyCLI::Context.message("core.app.deploy.help", ShopifyCLI::TOOL_NAME, ShopifyCLI::TOOL_NAME)
41
+ end
42
+
43
+ def self.extended_help
44
+ ShopifyCLI::Context.message("core.app.deploy.extended_help", ShopifyCLI::TOOL_NAME)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,19 @@
1
+ module ShopifyCLI
2
+ module Commands
3
+ class App
4
+ class Open < ShopifyCLI::Command::AppSubCommand
5
+ def call(*)
6
+ project = ShopifyCLI::Project.current
7
+ Services::App::OpenService.call(
8
+ project: project,
9
+ context: @ctx
10
+ )
11
+ end
12
+
13
+ def self.help
14
+ ShopifyCLI::Context.message("core.app.open.help", ShopifyCLI::TOOL_NAME, ShopifyCLI::TOOL_NAME)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end