shopify-cli 2.2.2 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (267) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -0
  3. data/.github/ISSUE_TEMPLATE.md +0 -4
  4. data/.github/workflows/shopify.yml +104 -0
  5. data/.gitignore +3 -0
  6. data/.rubocop.yml +14 -14
  7. data/.rubocop_todo.yml +3 -3
  8. data/CHANGELOG.md +30 -0
  9. data/CONTRIBUTING.md +23 -0
  10. data/Dockerfile +17 -0
  11. data/Gemfile +1 -0
  12. data/Gemfile.lock +67 -24
  13. data/RELEASING.md +1 -1
  14. data/Rakefile +75 -18
  15. data/bin/console +11 -0
  16. data/bin/shopify +16 -4
  17. data/dev.yml +14 -1
  18. data/ext/shopify-cli/extconf.rb +2 -0
  19. data/ext/shopify-extensions/extconf.rb +21 -0
  20. data/ext/shopify-extensions/shopify_extensions.rb +152 -0
  21. data/ext/shopify-extensions/version +1 -0
  22. data/lib/project_types/extension/cli.rb +19 -3
  23. data/lib/project_types/extension/commands/build.rb +32 -3
  24. data/lib/project_types/extension/commands/check.rb +2 -2
  25. data/lib/project_types/extension/commands/connect.rb +1 -1
  26. data/lib/project_types/extension/commands/create.rb +59 -16
  27. data/lib/project_types/extension/commands/extension_command.rb +1 -1
  28. data/lib/project_types/extension/commands/info.rb +1 -1
  29. data/lib/project_types/extension/commands/push.rb +1 -1
  30. data/lib/project_types/extension/commands/register.rb +2 -2
  31. data/lib/project_types/extension/commands/serve.rb +5 -5
  32. data/lib/project_types/extension/commands/tunnel.rb +6 -6
  33. data/lib/project_types/extension/extension_project.rb +4 -4
  34. data/lib/project_types/extension/features/argo.rb +3 -3
  35. data/lib/project_types/extension/features/argo_config.rb +5 -5
  36. data/lib/project_types/extension/features/argo_serve.rb +21 -6
  37. data/lib/project_types/extension/features/argo_setup.rb +1 -1
  38. data/lib/project_types/extension/features/argo_setup_step.rb +1 -1
  39. data/lib/project_types/extension/features/argo_setup_steps.rb +2 -2
  40. data/lib/project_types/extension/forms/connect.rb +2 -2
  41. data/lib/project_types/extension/forms/create.rb +6 -3
  42. data/lib/project_types/extension/forms/questions/ask_app.rb +2 -2
  43. data/lib/project_types/extension/forms/questions/ask_name.rb +1 -1
  44. data/lib/project_types/extension/forms/questions/ask_registration.rb +2 -2
  45. data/lib/project_types/extension/forms/questions/ask_template.rb +44 -0
  46. data/lib/project_types/extension/forms/questions/ask_type.rb +2 -2
  47. data/lib/project_types/extension/messages/message_loading.rb +2 -2
  48. data/lib/project_types/extension/messages/messages.rb +3 -0
  49. data/lib/project_types/extension/models/development_server.rb +78 -0
  50. data/lib/project_types/extension/models/development_server_requirements.rb +35 -0
  51. data/lib/project_types/extension/models/lazy_specification_handler.rb +1 -1
  52. data/lib/project_types/extension/models/server_config/base.rb +31 -0
  53. data/lib/project_types/extension/models/server_config/development.rb +23 -0
  54. data/lib/project_types/extension/models/server_config/development_entries.rb +38 -0
  55. data/lib/project_types/extension/models/server_config/development_renderer.rb +30 -0
  56. data/lib/project_types/extension/models/server_config/extension.rb +35 -0
  57. data/lib/project_types/extension/models/server_config/root.rb +18 -0
  58. data/lib/project_types/extension/models/server_config/user.rb +10 -0
  59. data/lib/project_types/extension/models/specification.rb +1 -1
  60. data/lib/project_types/extension/models/specification_handlers/checkout_ui_extension.rb +1 -1
  61. data/lib/project_types/extension/models/specification_handlers/default.rb +14 -2
  62. data/lib/project_types/extension/models/specification_handlers/theme_app_extension.rb +1 -1
  63. data/lib/project_types/extension/models/specifications.rb +4 -4
  64. data/lib/project_types/extension/tasks/choose_next_available_port.rb +2 -2
  65. data/lib/project_types/extension/tasks/configure_features.rb +1 -1
  66. data/lib/project_types/extension/tasks/configure_options.rb +1 -1
  67. data/lib/project_types/extension/tasks/converters/product_converter.rb +1 -1
  68. data/lib/project_types/extension/tasks/converters/server_config_converter.rb +31 -0
  69. data/lib/project_types/extension/tasks/create_extension.rb +2 -2
  70. data/lib/project_types/extension/tasks/fetch_specifications.rb +2 -2
  71. data/lib/project_types/extension/tasks/find_npm_packages.rb +5 -5
  72. data/lib/project_types/extension/tasks/get_app.rb +2 -2
  73. data/lib/project_types/extension/tasks/get_apps.rb +2 -2
  74. data/lib/project_types/extension/tasks/get_extensions.rb +2 -2
  75. data/lib/project_types/extension/tasks/get_product.rb +2 -2
  76. data/lib/project_types/extension/tasks/load_server_config.rb +23 -0
  77. data/lib/project_types/extension/tasks/run_extension_command.rb +81 -0
  78. data/lib/project_types/extension/tasks/update_draft.rb +2 -2
  79. data/lib/project_types/node/cli.rb +3 -3
  80. data/lib/project_types/node/commands/connect.rb +4 -4
  81. data/lib/project_types/node/commands/create.rb +10 -14
  82. data/lib/project_types/node/commands/deploy/heroku.rb +4 -4
  83. data/lib/project_types/node/commands/deploy.rb +3 -3
  84. data/lib/project_types/node/commands/generate.rb +2 -2
  85. data/lib/project_types/node/commands/open.rb +3 -3
  86. data/lib/project_types/node/commands/serve.rb +15 -7
  87. data/lib/project_types/node/commands/tunnel.rb +6 -6
  88. data/lib/project_types/node/forms/create.rb +3 -3
  89. data/lib/project_types/node/messages/messages.rb +3 -0
  90. data/lib/project_types/php/cli.rb +27 -0
  91. data/lib/project_types/php/commands/connect.rb +19 -0
  92. data/lib/project_types/php/commands/create.rb +143 -0
  93. data/lib/project_types/php/commands/deploy/heroku.rb +129 -0
  94. data/lib/project_types/php/commands/deploy.rb +32 -0
  95. data/lib/project_types/php/commands/open.rb +16 -0
  96. data/lib/project_types/php/commands/serve.rb +51 -0
  97. data/lib/project_types/php/commands/tunnel.rb +37 -0
  98. data/lib/project_types/php/forms/create.rb +45 -0
  99. data/lib/project_types/php/messages/messages.rb +191 -0
  100. data/lib/project_types/rails/cli.rb +3 -3
  101. data/lib/project_types/rails/commands/connect.rb +4 -4
  102. data/lib/project_types/rails/commands/create.rb +12 -16
  103. data/lib/project_types/rails/commands/deploy/heroku.rb +4 -4
  104. data/lib/project_types/rails/commands/deploy.rb +3 -3
  105. data/lib/project_types/rails/commands/generate/webhook.rb +3 -3
  106. data/lib/project_types/rails/commands/generate.rb +3 -3
  107. data/lib/project_types/rails/commands/open.rb +3 -3
  108. data/lib/project_types/rails/commands/serve.rb +8 -8
  109. data/lib/project_types/rails/commands/tunnel.rb +6 -6
  110. data/lib/project_types/rails/forms/create.rb +3 -3
  111. data/lib/project_types/rails/gem.rb +1 -1
  112. data/lib/project_types/rails/ruby.rb +1 -1
  113. data/lib/project_types/script/cli.rb +16 -6
  114. data/lib/project_types/script/commands/create.rb +4 -2
  115. data/lib/project_types/script/commands/push.rb +2 -2
  116. data/lib/project_types/script/config/extension_points.yml +30 -29
  117. data/lib/project_types/script/forms/create.rb +1 -1
  118. data/lib/project_types/script/layers/application/create_script.rb +32 -12
  119. data/lib/project_types/script/layers/application/extension_points.rb +4 -4
  120. data/lib/project_types/script/layers/application/push_script.rb +13 -1
  121. data/lib/project_types/script/layers/domain/extension_point.rb +13 -45
  122. data/lib/project_types/script/layers/domain/push_package.rb +0 -12
  123. data/lib/project_types/script/layers/domain/script_project.rb +2 -2
  124. data/lib/project_types/script/layers/infrastructure/api_clients/partners_proxy_api_client.rb +57 -0
  125. data/lib/project_types/script/layers/infrastructure/api_clients/script_service_api_client.rb +35 -0
  126. data/lib/project_types/script/layers/infrastructure/command_runner.rb +1 -1
  127. data/lib/project_types/script/layers/infrastructure/errors.rb +5 -0
  128. data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb +10 -90
  129. data/lib/project_types/script/layers/infrastructure/languages/project_creator.rb +76 -11
  130. data/lib/project_types/script/layers/infrastructure/languages/task_runner.rb +1 -1
  131. data/lib/project_types/script/layers/infrastructure/languages/typescript_project_creator.rb +33 -0
  132. data/lib/project_types/script/layers/infrastructure/languages/typescript_task_runner.rb +105 -0
  133. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +1 -1
  134. data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +6 -6
  135. data/lib/project_types/script/layers/infrastructure/script_service.rb +25 -144
  136. data/lib/project_types/script/layers/infrastructure/script_uploader.rb +27 -0
  137. data/lib/project_types/script/layers/infrastructure/service_locator.rb +20 -0
  138. data/lib/project_types/script/messages/messages.rb +4 -0
  139. data/lib/project_types/script/tasks/ensure_env.rb +7 -7
  140. data/lib/project_types/script/ui/error_handler.rb +84 -76
  141. data/lib/project_types/script/ui/printing_spinner.rb +1 -1
  142. data/lib/project_types/theme/cli.rb +3 -3
  143. data/lib/project_types/theme/commands/check.rb +3 -3
  144. data/lib/project_types/theme/commands/delete.rb +7 -7
  145. data/lib/project_types/theme/commands/init.rb +3 -3
  146. data/lib/project_types/theme/commands/language_server.rb +2 -2
  147. data/lib/project_types/theme/commands/package.rb +2 -2
  148. data/lib/project_types/theme/commands/publish.rb +5 -5
  149. data/lib/project_types/theme/commands/pull.rb +15 -9
  150. data/lib/project_types/theme/commands/push.rb +18 -12
  151. data/lib/project_types/theme/commands/serve.rb +4 -4
  152. data/lib/project_types/theme/forms/confirm_store.rb +1 -1
  153. data/lib/project_types/theme/forms/select.rb +2 -2
  154. data/lib/{shopify-cli → shopify_cli}/admin_api/populate_resource_command.rb +3 -3
  155. data/lib/{shopify-cli → shopify_cli}/admin_api/schema.rb +4 -4
  156. data/lib/{shopify-cli → shopify_cli}/admin_api.rb +27 -27
  157. data/lib/{shopify-cli → shopify_cli}/api.rb +8 -8
  158. data/lib/shopify_cli/command/app_sub_command.rb +16 -0
  159. data/lib/{shopify-cli → shopify_cli}/command.rb +3 -3
  160. data/lib/{shopify-cli → shopify_cli}/commands/config.rb +14 -14
  161. data/lib/{shopify-cli → shopify_cli}/commands/help.rb +4 -4
  162. data/lib/{shopify-cli → shopify_cli}/commands/login.rb +7 -7
  163. data/lib/shopify_cli/commands/logout.rb +39 -0
  164. data/lib/{shopify-cli → shopify_cli}/commands/populate/customer.rb +4 -4
  165. data/lib/{shopify-cli → shopify_cli}/commands/populate/draft_order.rb +4 -4
  166. data/lib/{shopify-cli → shopify_cli}/commands/populate/product.rb +4 -4
  167. data/lib/shopify_cli/commands/populate.rb +23 -0
  168. data/lib/shopify_cli/commands/store.rb +15 -0
  169. data/lib/{shopify-cli → shopify_cli}/commands/switch.rb +5 -5
  170. data/lib/{shopify-cli → shopify_cli}/commands/system.rb +10 -10
  171. data/lib/shopify_cli/commands/version.rb +15 -0
  172. data/lib/{shopify-cli → shopify_cli}/commands/whoami.rb +7 -7
  173. data/lib/shopify_cli/commands.rb +34 -0
  174. data/lib/{shopify-cli → shopify_cli}/connect.rb +3 -3
  175. data/lib/shopify_cli/constants.rb +54 -0
  176. data/lib/{shopify-cli → shopify_cli}/context.rb +6 -6
  177. data/lib/{shopify-cli → shopify_cli}/core/entry_point.rb +7 -7
  178. data/lib/{shopify-cli → shopify_cli}/core/executor.rb +8 -4
  179. data/lib/{shopify-cli → shopify_cli}/core/finalize.rb +1 -1
  180. data/lib/{shopify-cli → shopify_cli}/core/help_resolver.rb +2 -2
  181. data/lib/{shopify-cli → shopify_cli}/core/monorail.rb +8 -8
  182. data/lib/shopify_cli/core.rb +8 -0
  183. data/lib/{shopify-cli → shopify_cli}/db.rb +8 -8
  184. data/lib/shopify_cli/environment.rb +91 -0
  185. data/lib/shopify_cli/exception_reporter/permission_controller.rb +54 -0
  186. data/lib/shopify_cli/exception_reporter.rb +55 -0
  187. data/lib/{shopify-cli → shopify_cli}/feature.rb +8 -8
  188. data/lib/{shopify-cli → shopify_cli}/form.rb +2 -2
  189. data/lib/{shopify-cli → shopify_cli}/git.rb +38 -8
  190. data/lib/{shopify-cli → shopify_cli}/helpers/haikunator.rb +1 -1
  191. data/lib/shopify_cli/helpers.rb +5 -0
  192. data/lib/{shopify-cli → shopify_cli}/heroku.rb +38 -13
  193. data/lib/{shopify-cli → shopify_cli}/http_request.rb +1 -1
  194. data/lib/{shopify-cli → shopify_cli}/identity_auth/servlet.rb +1 -1
  195. data/lib/{shopify-cli → shopify_cli}/identity_auth.rb +24 -31
  196. data/lib/{shopify-cli → shopify_cli}/js_deps.rb +7 -7
  197. data/lib/{shopify-cli → shopify_cli}/js_system.rb +10 -10
  198. data/lib/{shopify-cli → shopify_cli}/lazy_delegator.rb +2 -2
  199. data/lib/{shopify-cli → shopify_cli}/messages/messages.rb +44 -2
  200. data/lib/{shopify-cli → shopify_cli}/method_object.rb +15 -8
  201. data/lib/shopify_cli/migrator/migration.rb +27 -0
  202. data/lib/shopify_cli/migrator/migrations/1631709766_noop.rb +13 -0
  203. data/lib/shopify_cli/migrator.rb +48 -0
  204. data/lib/{shopify-cli → shopify_cli}/options.rb +1 -1
  205. data/lib/{shopify-cli → shopify_cli}/packager.rb +8 -8
  206. data/lib/{shopify-cli → shopify_cli}/partners_api/organizations.rb +1 -1
  207. data/lib/{shopify-cli → shopify_cli}/partners_api.rb +16 -40
  208. data/lib/shopify_cli/php_deps.rb +102 -0
  209. data/lib/{shopify-cli → shopify_cli}/process_supervision.rb +23 -21
  210. data/lib/{shopify-cli → shopify_cli}/project.rb +15 -15
  211. data/lib/{shopify-cli → shopify_cli}/project_commands.rb +3 -3
  212. data/lib/{shopify-cli → shopify_cli}/project_type.rb +5 -5
  213. data/lib/{shopify-cli → shopify_cli}/resolve_constant.rb +5 -5
  214. data/lib/{shopify-cli → shopify_cli}/resources/env_file.rb +1 -1
  215. data/lib/shopify_cli/resources.rb +5 -0
  216. data/lib/{shopify-cli → shopify_cli}/result.rb +11 -11
  217. data/lib/{shopify-cli → shopify_cli}/shopifolk.rb +6 -6
  218. data/lib/{shopify-cli → shopify_cli}/sub_command.rb +1 -1
  219. data/lib/{shopify-cli → shopify_cli}/task.rb +1 -1
  220. data/lib/{shopify-cli → shopify_cli}/tasks/confirm_store.rb +3 -3
  221. data/lib/{shopify-cli → shopify_cli}/tasks/create_api_client.rb +4 -4
  222. data/lib/shopify_cli/tasks/ensure_authenticated.rb +13 -0
  223. data/lib/{shopify-cli → shopify_cli}/tasks/ensure_dev_store.rb +5 -5
  224. data/lib/{shopify-cli → shopify_cli}/tasks/ensure_env.rb +3 -3
  225. data/lib/{shopify-cli → shopify_cli}/tasks/ensure_loopback_url.rb +4 -4
  226. data/lib/{shopify-cli → shopify_cli}/tasks/ensure_project_type.rb +3 -3
  227. data/lib/{shopify-cli → shopify_cli}/tasks/select_org_and_shop.rb +8 -8
  228. data/lib/{shopify-cli → shopify_cli}/tasks/update_dashboard_urls.rb +6 -6
  229. data/lib/{shopify-cli → shopify_cli}/tasks.rb +10 -10
  230. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/certificate_manager.rb +5 -5
  231. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/header_hash.rb +5 -1
  232. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/hot-reload.js +0 -0
  233. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/hot_reload.rb +5 -6
  234. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/local_assets.rb +1 -1
  235. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/proxy.rb +15 -3
  236. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/sse.rb +1 -1
  237. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/watcher.rb +1 -1
  238. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/web_server.rb +1 -1
  239. data/lib/{shopify-cli → shopify_cli}/theme/dev_server.rb +3 -3
  240. data/lib/shopify_cli/theme/development_theme.rb +83 -0
  241. data/lib/{shopify-cli → shopify_cli}/theme/file.rb +12 -4
  242. data/lib/{shopify-cli → shopify_cli}/theme/ignore_filter.rb +8 -1
  243. data/lib/{shopify-cli → shopify_cli}/theme/mime_type.rb +1 -1
  244. data/lib/{shopify-cli → shopify_cli}/theme/syncer.rb +7 -7
  245. data/lib/{shopify-cli → shopify_cli}/theme/theme.rb +4 -4
  246. data/lib/{shopify-cli → shopify_cli}/transform_data_structure.rb +4 -4
  247. data/lib/{shopify-cli → shopify_cli}/tunnel.rb +14 -14
  248. data/lib/shopify_cli/version.rb +3 -0
  249. data/lib/shopify_cli.rb +61 -50
  250. data/shopify-cli.gemspec +13 -5
  251. data/utilities/docker.rb +47 -0
  252. data/utilities/utilities.rb +5 -0
  253. metadata +155 -97
  254. data/.github/workflows/build.yml +0 -28
  255. data/lib/project_types/script/layers/infrastructure/languages/rust_project_creator.rb +0 -73
  256. data/lib/project_types/script/layers/infrastructure/languages/rust_task_runner.rb +0 -60
  257. data/lib/shopify-cli/commands/logout.rb +0 -39
  258. data/lib/shopify-cli/commands/populate.rb +0 -23
  259. data/lib/shopify-cli/commands/store.rb +0 -15
  260. data/lib/shopify-cli/commands/version.rb +0 -15
  261. data/lib/shopify-cli/commands.rb +0 -34
  262. data/lib/shopify-cli/core.rb +0 -8
  263. data/lib/shopify-cli/helpers.rb +0 -5
  264. data/lib/shopify-cli/resources.rb +0 -5
  265. data/lib/shopify-cli/tasks/ensure_authenticated.rb +0 -13
  266. data/lib/shopify-cli/theme/development_theme.rb +0 -69
  267. data/lib/shopify-cli/version.rb +0 -3
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  module Node
3
3
  class Command
4
- class Serve < ShopifyCli::SubCommand
4
+ class Serve < ShopifyCLI::SubCommand
5
5
  prerequisite_task ensure_project_type: :node
6
6
  prerequisite_task :ensure_env, :ensure_dev_store
7
7
 
@@ -9,14 +9,15 @@ module Node
9
9
  parser.on("--host=HOST") do |h|
10
10
  flags[:host] = h.gsub('"', "")
11
11
  end
12
+ parser.on("--port=PORT") { |port| flags[:port] = port }
12
13
  end
13
14
 
14
15
  def call(*)
15
- project = ShopifyCli::Project.current
16
- url = options.flags[:host] || ShopifyCli::Tunnel.start(@ctx)
16
+ project = ShopifyCLI::Project.current
17
+ url = options.flags[:host] || ShopifyCLI::Tunnel.start(@ctx)
17
18
  @ctx.abort(@ctx.message("node.serve.error.host_must_be_https")) if url.match(/^https/i).nil?
18
19
  project.env.update(@ctx, :host, url)
19
- ShopifyCli::Tasks::UpdateDashboardURLS.call(
20
+ ShopifyCLI::Tasks::UpdateDashboardURLS.call(
20
21
  @ctx,
21
22
  url: url,
22
23
  callback_url: "/auth/callback",
@@ -29,17 +30,24 @@ module Node
29
30
 
30
31
  CLI::UI::Frame.open(@ctx.message("node.serve.running_server")) do
31
32
  env = project.env.to_h
32
- env["PORT"] = ShopifyCli::Tunnel::PORT.to_s
33
+ env["PORT"] = port.to_s
33
34
  @ctx.system("npm run dev", env: env)
34
35
  end
35
36
  end
36
37
 
38
+ def port
39
+ return ShopifyCLI::Tunnel::PORT.to_s unless options.flags.key?(:port)
40
+ port = options.flags[:port].to_i
41
+ @ctx.abort(@ctx.message("node.serve.error.invalid_port", options.flags[:port])) unless port > 0
42
+ port
43
+ end
44
+
37
45
  def self.help
38
- ShopifyCli::Context.message("node.serve.help", ShopifyCli::TOOL_NAME)
46
+ ShopifyCLI::Context.message("node.serve.help", ShopifyCLI::TOOL_NAME)
39
47
  end
40
48
 
41
49
  def self.extended_help
42
- ShopifyCli::Context.message("node.serve.extended_help")
50
+ ShopifyCLI::Context.message("node.serve.extended_help")
43
51
  end
44
52
  end
45
53
  end
@@ -4,7 +4,7 @@ require "shopify_cli"
4
4
 
5
5
  module Node
6
6
  class Command
7
- class Tunnel < ShopifyCli::SubCommand
7
+ class Tunnel < ShopifyCLI::SubCommand
8
8
  # subcommands :auth, :start, :stop
9
9
 
10
10
  prerequisite_task ensure_project_type: :node
@@ -18,23 +18,23 @@ module Node
18
18
  @ctx.puts(@ctx.message("node.tunnel.error.token_argument_missing"))
19
19
  @ctx.puts("#{self.class.help}\n#{self.class.extended_help}")
20
20
  else
21
- ShopifyCli::Tunnel.auth(@ctx, token)
21
+ ShopifyCLI::Tunnel.auth(@ctx, token)
22
22
  end
23
23
  when "start"
24
- ShopifyCli::Tunnel.start(@ctx)
24
+ ShopifyCLI::Tunnel.start(@ctx)
25
25
  when "stop"
26
- ShopifyCli::Tunnel.stop(@ctx)
26
+ ShopifyCLI::Tunnel.stop(@ctx)
27
27
  else
28
28
  @ctx.puts(self.class.help)
29
29
  end
30
30
  end
31
31
 
32
32
  def self.help
33
- ShopifyCli::Context.message("node.tunnel.help", ShopifyCli::TOOL_NAME)
33
+ ShopifyCLI::Context.message("node.tunnel.help", ShopifyCLI::TOOL_NAME)
34
34
  end
35
35
 
36
36
  def self.extended_help
37
- ShopifyCli::Context.message("node.tunnel.extended_help", ShopifyCli::TOOL_NAME)
37
+ ShopifyCLI::Context.message("node.tunnel.extended_help", ShopifyCLI::TOOL_NAME)
38
38
  end
39
39
  end
40
40
  end
@@ -2,7 +2,7 @@ require "uri"
2
2
 
3
3
  module Node
4
4
  module Forms
5
- class Create < ShopifyCli::Form
5
+ class Create < ShopifyCLI::Form
6
6
  attr_accessor :name
7
7
  flag_arguments :title, :organization_id, :shop_domain, :type
8
8
 
@@ -10,7 +10,7 @@ module Node
10
10
  self.title ||= CLI::UI::Prompt.ask(ctx.message("node.forms.create.app_name"))
11
11
  self.name = format_name
12
12
  self.type = ask_type
13
- res = ShopifyCli::Tasks::SelectOrgAndShop.call(ctx, organization_id: organization_id, shop_domain: shop_domain)
13
+ res = ShopifyCLI::Tasks::SelectOrgAndShop.call(ctx, organization_id: organization_id, shop_domain: shop_domain)
14
14
  self.organization_id = res[:organization_id]
15
15
  self.shop_domain = res[:shop_domain]
16
16
  end
@@ -34,7 +34,7 @@ module Node
34
34
  end
35
35
  end
36
36
 
37
- unless ShopifyCli::Tasks::CreateApiClient::VALID_APP_TYPES.include?(type)
37
+ unless ShopifyCLI::Tasks::CreateApiClient::VALID_APP_TYPES.include?(type)
38
38
  ctx.abort(ctx.message("node.forms.create.error.invalid_app_type", type))
39
39
  end
40
40
  ctx.puts(ctx.message("node.forms.create.app_type.selected", type))
@@ -119,10 +119,12 @@ module Node
119
119
  extended_help: <<~HELP,
120
120
  {{bold:Options:}}
121
121
  {{cyan:--host=HOST}}: Bypass running tunnel and use custom host. HOST must be HTTPS url.
122
+ {{cyan:--port=PORT}}: Use custom port.
122
123
  HELP
123
124
 
124
125
  error: {
125
126
  host_must_be_https: "HOST must be a HTTPS url.",
127
+ invalid_port: "%s is not a valid port.",
126
128
  },
127
129
 
128
130
  open_info: <<~MESSAGE,
@@ -154,6 +156,7 @@ module Node
154
156
  error: {
155
157
  token_argument_missing: "{{x}} {{red:auth requires a token argument}}\n\n",
156
158
  },
159
+
157
160
  },
158
161
 
159
162
  forms: {
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+ module PHP
3
+ class Project < ShopifyCLI::ProjectType
4
+ require Project.project_filepath("messages/messages")
5
+ register_messages(PHP::Messages::MESSAGES)
6
+ end
7
+
8
+ # define/autoload project specific Commands
9
+ class Command < ShopifyCLI::ProjectCommands
10
+ subcommand :Connect, "connect", Project.project_filepath("commands/connect")
11
+ subcommand :Create, "create", Project.project_filepath("commands/create")
12
+ subcommand :Deploy, "deploy", Project.project_filepath("commands/deploy")
13
+ subcommand :Open, "open", Project.project_filepath("commands/open")
14
+ subcommand :Serve, "serve", Project.project_filepath("commands/serve")
15
+ subcommand :Tunnel, "tunnel", Project.project_filepath("commands/tunnel")
16
+ end
17
+ ShopifyCLI::Commands.register("PHP::Command", "php")
18
+
19
+ # define/autoload project specific Tasks
20
+ module Tasks
21
+ end
22
+
23
+ # define/autoload project specific Forms
24
+ module Forms
25
+ autoload :Create, Project.project_filepath("forms/create")
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+ module PHP
3
+ class Command
4
+ class Connect < ShopifyCLI::SubCommand
5
+ def call(*)
6
+ if ShopifyCLI::Project.has_current? && ShopifyCLI::Project.current.env
7
+ @ctx.puts(@ctx.message("php.connect.production_warning"))
8
+ end
9
+
10
+ app = ShopifyCLI::Connect.new(@ctx).default_connect("php")
11
+ @ctx.done(@ctx.message("php.connect.connected", app))
12
+ end
13
+
14
+ def self.help
15
+ ShopifyCLI::Context.message("php.connect.help", ShopifyCLI::TOOL_NAME, ShopifyCLI::TOOL_NAME)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,143 @@
1
+ # frozen_string_literal: true
2
+ require "semantic/semantic"
3
+
4
+ module PHP
5
+ class Command
6
+ class Create < ShopifyCLI::SubCommand
7
+ options do |parser, flags|
8
+ parser.on("--name=NAME") { |name| flags[:title] = name }
9
+ parser.on("--organization-id=ID") { |organization_id| flags[:organization_id] = organization_id }
10
+ parser.on("--store=MYSHOPIFYDOMAIN") { |url| flags[:shop_domain] = url }
11
+ parser.on("--type=APPTYPE") { |type| flags[:type] = type }
12
+ parser.on("--verbose") { flags[:verbose] = true }
13
+ end
14
+
15
+ def call(args, _name)
16
+ form = Forms::Create.ask(@ctx, args, options.flags)
17
+ return @ctx.puts(self.class.help) if form.nil?
18
+
19
+ check_php
20
+ check_composer
21
+ check_npm
22
+ app_id = build(form)
23
+
24
+ ShopifyCLI::Project.write(
25
+ @ctx,
26
+ project_type: "php",
27
+ organization_id: form.organization_id,
28
+ )
29
+
30
+ partners_url = ShopifyCLI::PartnersAPI.partners_url_for(form.organization_id, app_id)
31
+
32
+ @ctx.puts(@ctx.message("apps.create.info.created", form.title, partners_url))
33
+ @ctx.puts(@ctx.message("apps.create.info.serve", form.name, ShopifyCLI::TOOL_NAME, "php"))
34
+ unless ShopifyCLI::Shopifolk.acting_as_shopify_organization?
35
+ @ctx.puts(@ctx.message("apps.create.info.install", partners_url, form.title))
36
+ end
37
+ end
38
+
39
+ def self.help
40
+ ShopifyCLI::Context.message("php.create.help", ShopifyCLI::TOOL_NAME, ShopifyCLI::TOOL_NAME)
41
+ end
42
+
43
+ private
44
+
45
+ def check_php
46
+ cmd_path = @ctx.which("php")
47
+ @ctx.abort(@ctx.message("php.create.error.php_required")) if cmd_path.nil?
48
+
49
+ version, stat = @ctx.capture2e("php", "-r", "echo phpversion();")
50
+ @ctx.abort(@ctx.message("php.create.error.php_version_failure")) unless stat.success?
51
+
52
+ if ::Semantic::Version.new(version) < ::Semantic::Version.new("7.3.0")
53
+ @ctx.abort(@ctx.message("php.create.error.php_version_too_low", "7.3"))
54
+ end
55
+
56
+ @ctx.done(@ctx.message("php.create.php_version", version))
57
+ end
58
+
59
+ def check_composer
60
+ cmd_path = @ctx.which("composer")
61
+ @ctx.abort(@ctx.message("php.create.error.composer_required")) if cmd_path.nil?
62
+ end
63
+
64
+ def check_npm
65
+ cmd_path = @ctx.which("npm")
66
+ @ctx.abort(@ctx.message("php.create.error.npm_required")) if cmd_path.nil?
67
+
68
+ version, stat = @ctx.capture2e("npm", "-v")
69
+ @ctx.abort(@ctx.message("php.create.error.npm_version_failure")) unless stat.success?
70
+
71
+ @ctx.done(@ctx.message("php.create.npm_version", version))
72
+ end
73
+
74
+ def build(form)
75
+ ShopifyCLI::Git.clone("https://github.com/Shopify/shopify-app-php.git", form.name)
76
+
77
+ @ctx.root = File.join(@ctx.root, form.name)
78
+ @ctx.chdir(@ctx.root)
79
+
80
+ api_client = ShopifyCLI::Tasks::CreateApiClient.call(
81
+ @ctx,
82
+ org_id: form.organization_id,
83
+ title: form.title,
84
+ type: form.type,
85
+ )
86
+
87
+ # Override the example settings with our own
88
+ @ctx.cp(".env.example", ".env")
89
+
90
+ env_file = ShopifyCLI::Resources::EnvFile.read
91
+ env_file.api_key = api_client["apiKey"]
92
+ env_file.secret = api_client["apiSecretKeys"].first["secret"]
93
+ env_file.shop = form.shop_domain
94
+ env_file.host = "localhost"
95
+ env_file.scopes = "write_products,write_draft_orders,write_customers"
96
+ env_file.extra["DB_DATABASE"] = File.join(@ctx.root, env_file.extra["DB_DATABASE"])
97
+ env_file.write(@ctx)
98
+
99
+ ShopifyCLI::PHPDeps.install(@ctx, !options.flags[:verbose].nil?)
100
+
101
+ set_npm_config
102
+ ShopifyCLI::JsDeps.install(@ctx, !options.flags[:verbose].nil?)
103
+
104
+ title = @ctx.message("php.create.app_setting_up")
105
+ success = @ctx.message("php.create.app_set_up")
106
+ failure = @ctx.message("php.create.error.app_setup")
107
+ CLI::UI::Frame.open(title, success_text: success, failure_text: failure) do
108
+ FileUtils.touch(env_file.extra["DB_DATABASE"])
109
+ @ctx.system("php", "artisan", "key:generate")
110
+ @ctx.system("php", "artisan", "migrate")
111
+ end
112
+
113
+ begin
114
+ @ctx.rm_r(".git")
115
+ @ctx.rm_r(".github")
116
+ rescue Errno::ENOENT => e
117
+ @ctx.debug(e)
118
+ end
119
+
120
+ api_client["id"]
121
+ end
122
+
123
+ def set_npm_config
124
+ # check available npmrc (either user or system) for production registry
125
+ registry, _ = @ctx.capture2("npm config get @shopify:registry")
126
+ return if registry.include?("https://registry.yarnpkg.com")
127
+
128
+ # available npmrc doesn't have production registry =>
129
+ # set a project-based .npmrc
130
+ @ctx.system(
131
+ "npm",
132
+ "--userconfig",
133
+ "./.npmrc",
134
+ "config",
135
+ "set",
136
+ "@shopify:registry",
137
+ "https://registry.yarnpkg.com",
138
+ chdir: @ctx.root
139
+ )
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+ require "shopify_cli"
3
+
4
+ module PHP
5
+ class Command
6
+ class Deploy
7
+ class Heroku
8
+ def self.help
9
+ ShopifyCLI::Context.message("php.deploy.heroku.help", ShopifyCLI::TOOL_NAME)
10
+ end
11
+
12
+ def self.start(ctx)
13
+ spin_group = CLI::UI::SpinGroup.new
14
+ heroku_service = ShopifyCLI::Heroku.new(ctx)
15
+
16
+ spin_group.add(ctx.message("php.deploy.heroku.downloading")) do |spinner|
17
+ heroku_service.download
18
+ spinner.update_title(ctx.message("php.deploy.heroku.downloaded"))
19
+ end
20
+ spin_group.wait
21
+
22
+ install_message = ctx.message(
23
+ ctx.windows? ? "php.deploy.heroku.installing_windows" : "php.deploy.heroku.installing"
24
+ )
25
+ spin_group.add(install_message) do |spinner|
26
+ heroku_service.install
27
+ spinner.update_title(ctx.message("php.deploy.heroku.installed"))
28
+ end
29
+ spin_group.wait
30
+
31
+ spin_group.add(ctx.message("php.deploy.heroku.git.checking")) do |spinner|
32
+ ShopifyCLI::Git.init(ctx)
33
+ spinner.update_title(ctx.message("php.deploy.heroku.git.initialized"))
34
+ end
35
+ spin_group.wait
36
+
37
+ if (account = heroku_service.whoami)
38
+ ctx.puts(ctx.message("php.deploy.heroku.authenticated_with_account", account))
39
+ else
40
+ CLI::UI::Frame.open(
41
+ ctx.message("php.deploy.heroku.authenticating"),
42
+ success_text: ctx.message("php.deploy.heroku.authenticated")
43
+ ) do
44
+ heroku_service.authenticate
45
+ end
46
+ end
47
+
48
+ if (app_name = heroku_service.app)
49
+ ctx.puts(ctx.message("php.deploy.heroku.app.selected", app_name))
50
+ else
51
+ app_type = CLI::UI::Prompt.ask(ctx.message("php.deploy.heroku.app.no_apps_found")) do |handler|
52
+ handler.option(ctx.message("php.deploy.heroku.app.create")) { :new }
53
+ handler.option(ctx.message("php.deploy.heroku.app.select")) { :existing }
54
+ end
55
+
56
+ if app_type == :existing
57
+ app_name = CLI::UI::Prompt.ask(ctx.message("php.deploy.heroku.app.name"))
58
+ CLI::UI::Frame.open(
59
+ ctx.message("php.deploy.heroku.app.selecting", app_name),
60
+ success_text: ctx.message("php.deploy.heroku.app.selected", app_name)
61
+ ) do
62
+ heroku_service.select_existing_app(app_name)
63
+ end
64
+ elsif app_type == :new
65
+ CLI::UI::Frame.open(
66
+ ctx.message("php.deploy.heroku.app.creating"),
67
+ success_text: ctx.message("php.deploy.heroku.app.created")
68
+ ) do
69
+ heroku_service.create_new_app
70
+ app_name = heroku_service.app
71
+ end
72
+ end
73
+ end
74
+
75
+ branches = ShopifyCLI::Git.branches(ctx)
76
+ if branches.length == 1
77
+ branch_to_deploy = branches[0]
78
+ ctx.puts(ctx.message("php.deploy.heroku.git.branch_selected", branch_to_deploy))
79
+ else
80
+ branch_to_deploy = CLI::UI::Prompt.ask(ctx.message("php.deploy.heroku.git.what_branch")) do |handler|
81
+ branches.each do |branch|
82
+ handler.option(branch) { branch }
83
+ end
84
+ end
85
+ end
86
+
87
+ app_url = "https://#{app_name}.herokuapp.com"
88
+
89
+ CLI::UI::Frame.open(
90
+ ctx.message("php.deploy.heroku.app.setting_configs"),
91
+ success_text: ctx.message("php.deploy.heroku.app.configs_set")
92
+ ) do
93
+ allowed_configs = [/SHOPIFY_API_KEY/, /SHOPIFY_API_SECRET/, /SCOPES/, /HOST/]
94
+
95
+ ShopifyCLI::Project.current.env.to_h.each do |config, value|
96
+ next unless allowed_configs.any? { |pattern| pattern.match?(config) }
97
+
98
+ value = app_url if config == "HOST"
99
+
100
+ current = heroku_service.get_config(config)
101
+ heroku_service.set_config(config, value) if current.nil? || current != value
102
+ end
103
+
104
+ current_key = heroku_service.get_config("APP_KEY")
105
+ if current_key.nil? || current_key.empty?
106
+ output, status = ctx.capture2e("php", "artisan", "key:generate", "--show")
107
+
108
+ ctx.abort(ctx.message("php.deploy.heroku.error.generate_app_key")) unless status.success?
109
+
110
+ heroku_service.set_config("APP_KEY", output.strip) if status.success?
111
+ end
112
+
113
+ heroku_service.add_buildpacks(["heroku/php", "heroku/nodejs"])
114
+ end
115
+
116
+ CLI::UI::Frame.open(
117
+ ctx.message("php.deploy.heroku.deploying"),
118
+ success_text: ctx.message("php.deploy.heroku.deployed")
119
+ ) do
120
+ heroku_service.deploy(branch_to_deploy)
121
+ end
122
+
123
+ heroku_command = heroku_service.heroku_command
124
+ ctx.puts(ctx.message("php.deploy.heroku.post_deploy", app_url, heroku_command))
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+ require "shopify_cli"
3
+
4
+ module PHP
5
+ class Command
6
+ class Deploy < ShopifyCLI::SubCommand
7
+ prerequisite_task ensure_project_type: :php
8
+
9
+ autoload :Heroku, Project.project_filepath("commands/deploy/heroku")
10
+
11
+ HEROKU = "heroku"
12
+
13
+ def call(args, _name)
14
+ subcommand = args.shift
15
+ case subcommand
16
+ when HEROKU
17
+ PHP::Command::Deploy::Heroku.start(@ctx)
18
+ else
19
+ @ctx.puts(self.class.help)
20
+ end
21
+ end
22
+
23
+ def self.help
24
+ ShopifyCLI::Context.message("php.deploy.help", ShopifyCLI::TOOL_NAME)
25
+ end
26
+
27
+ def self.extended_help
28
+ ShopifyCLI::Context.message("php.deploy.extended_help", ShopifyCLI::TOOL_NAME)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PHP
4
+ class Command
5
+ class Open < ShopifyCLI::SubCommand
6
+ def call(*)
7
+ project = ShopifyCLI::Project.current
8
+ @ctx.open_url!("#{project.env.host}/login?shop=#{project.env.shop}")
9
+ end
10
+
11
+ def self.help
12
+ ShopifyCLI::Context.message("php.open.help", ShopifyCLI::TOOL_NAME)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+ module PHP
3
+ class Command
4
+ class Serve < ShopifyCLI::SubCommand
5
+ PORT = 3000
6
+
7
+ prerequisite_task :ensure_env, :ensure_dev_store
8
+
9
+ options do |parser, flags|
10
+ parser.on("--host=HOST") do |h|
11
+ flags[:host] = h.gsub('"', "")
12
+ end
13
+ end
14
+
15
+ def call(*)
16
+ project = ShopifyCLI::Project.current
17
+ url = options.flags[:host] || ShopifyCLI::Tunnel.start(@ctx, port: PORT)
18
+ @ctx.abort(@ctx.message("php.serve.error.host_must_be_https")) if url.match(/^https/i).nil?
19
+ project.env.update(@ctx, :host, url)
20
+ ShopifyCLI::Tasks::UpdateDashboardURLS.call(
21
+ @ctx,
22
+ url: url,
23
+ callback_url: "/auth/callback",
24
+ )
25
+
26
+ if project.env.shop
27
+ project_url = "#{project.env.host}/login?shop=#{project.env.shop}"
28
+ @ctx.puts("\n" + @ctx.message("php.serve.open_info", project_url) + "\n")
29
+ end
30
+
31
+ CLI::UI::Frame.open(@ctx.message("php.serve.running_server")) do
32
+ if ShopifyCLI::ProcessSupervision.running?(:npm_watch)
33
+ ShopifyCLI::ProcessSupervision.stop(:npm_watch)
34
+ end
35
+ ShopifyCLI::ProcessSupervision.start(:npm_watch, "npm run watch", force_spawn: true)
36
+
37
+ env = project.env.to_h
38
+ @ctx.system("php", "artisan", "serve", "--port", PORT.to_s, env: env)
39
+ end
40
+ end
41
+
42
+ def self.help
43
+ ShopifyCLI::Context.message("php.serve.help", ShopifyCLI::TOOL_NAME)
44
+ end
45
+
46
+ def self.extended_help
47
+ ShopifyCLI::Context.message("php.serve.extended_help")
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "shopify_cli"
4
+
5
+ module PHP
6
+ class Command
7
+ class Tunnel < ShopifyCLI::SubCommand
8
+ def call(args, _name)
9
+ subcommand = args.shift
10
+ case subcommand
11
+ when "auth"
12
+ token = args.shift
13
+ if token.nil?
14
+ @ctx.puts(@ctx.message("php.tunnel.error.token_argument_missing"))
15
+ @ctx.puts("#{self.class.help}\n#{self.class.extended_help}")
16
+ else
17
+ ShopifyCLI::Tunnel.auth(@ctx, token)
18
+ end
19
+ when "start"
20
+ ShopifyCLI::Tunnel.start(@ctx)
21
+ when "stop"
22
+ ShopifyCLI::Tunnel.stop(@ctx)
23
+ else
24
+ @ctx.puts(self.class.help)
25
+ end
26
+ end
27
+
28
+ def self.help
29
+ ShopifyCLI::Context.message("php.tunnel.help", ShopifyCLI::TOOL_NAME)
30
+ end
31
+
32
+ def self.extended_help
33
+ ShopifyCLI::Context.message("php.tunnel.extended_help", ShopifyCLI::TOOL_NAME)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,45 @@
1
+ require "uri"
2
+
3
+ module PHP
4
+ module Forms
5
+ class Create < ShopifyCLI::Form
6
+ attr_accessor :name
7
+ flag_arguments :title, :organization_id, :shop_domain, :type
8
+
9
+ def ask
10
+ self.title ||= CLI::UI::Prompt.ask(ctx.message("php.forms.create.app_name"))
11
+ self.name = format_name
12
+ self.type = ask_type
13
+ res = ShopifyCLI::Tasks::SelectOrgAndShop.call(ctx, organization_id: organization_id, shop_domain: shop_domain)
14
+ self.organization_id = res[:organization_id]
15
+ self.shop_domain = res[:shop_domain]
16
+ end
17
+
18
+ private
19
+
20
+ def format_name
21
+ name = title.downcase.split(" ").join("_")
22
+
23
+ if name.include?("shopify")
24
+ ctx.abort(ctx.message("php.forms.create.error.invalid_app_name"))
25
+ end
26
+ name
27
+ end
28
+
29
+ def ask_type
30
+ if type.nil?
31
+ return CLI::UI::Prompt.ask(ctx.message("php.forms.create.app_type.select")) do |handler|
32
+ handler.option(ctx.message("php.forms.create.app_type.select_public")) { "public" }
33
+ handler.option(ctx.message("php.forms.create.app_type.select_custom")) { "custom" }
34
+ end
35
+ end
36
+
37
+ unless ShopifyCLI::Tasks::CreateApiClient::VALID_APP_TYPES.include?(type)
38
+ ctx.abort(ctx.message("php.forms.create.error.invalid_app_type", type))
39
+ end
40
+ ctx.puts(ctx.message("php.forms.create.app_type.selected", type))
41
+ type
42
+ end
43
+ end
44
+ end
45
+ end