shopify-cli 2.2.1 → 2.5.0

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 (249) 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 +2 -0
  6. data/.rubocop.yml +14 -14
  7. data/.rubocop_todo.yml +3 -3
  8. data/CHANGELOG.md +23 -0
  9. data/CONTRIBUTING.md +23 -0
  10. data/Dockerfile +19 -0
  11. data/Gemfile +1 -0
  12. data/Gemfile.lock +50 -13
  13. data/RELEASING.md +1 -1
  14. data/Rakefile +84 -18
  15. data/bin/shopify +3 -3
  16. data/dev.yml +11 -1
  17. data/ext/shopify-extensions/extconf.rb +21 -0
  18. data/ext/shopify-extensions/shopify_extensions.rb +152 -0
  19. data/ext/shopify-extensions/version +1 -0
  20. data/lib/project_types/extension/cli.rb +17 -3
  21. data/lib/project_types/extension/commands/build.rb +31 -3
  22. data/lib/project_types/extension/commands/check.rb +2 -2
  23. data/lib/project_types/extension/commands/connect.rb +1 -1
  24. data/lib/project_types/extension/commands/create.rb +59 -16
  25. data/lib/project_types/extension/commands/extension_command.rb +1 -1
  26. data/lib/project_types/extension/commands/info.rb +1 -1
  27. data/lib/project_types/extension/commands/push.rb +1 -1
  28. data/lib/project_types/extension/commands/register.rb +2 -2
  29. data/lib/project_types/extension/commands/serve.rb +5 -5
  30. data/lib/project_types/extension/commands/tunnel.rb +6 -6
  31. data/lib/project_types/extension/extension_project.rb +4 -4
  32. data/lib/project_types/extension/features/argo.rb +2 -2
  33. data/lib/project_types/extension/features/argo_config.rb +5 -5
  34. data/lib/project_types/extension/features/argo_serve.rb +20 -6
  35. data/lib/project_types/extension/features/argo_setup.rb +1 -1
  36. data/lib/project_types/extension/features/argo_setup_step.rb +1 -1
  37. data/lib/project_types/extension/features/argo_setup_steps.rb +2 -2
  38. data/lib/project_types/extension/forms/connect.rb +2 -2
  39. data/lib/project_types/extension/forms/create.rb +6 -3
  40. data/lib/project_types/extension/forms/questions/ask_app.rb +2 -2
  41. data/lib/project_types/extension/forms/questions/ask_name.rb +1 -1
  42. data/lib/project_types/extension/forms/questions/ask_registration.rb +2 -2
  43. data/lib/project_types/extension/forms/questions/ask_template.rb +44 -0
  44. data/lib/project_types/extension/forms/questions/ask_type.rb +2 -2
  45. data/lib/project_types/extension/messages/message_loading.rb +2 -2
  46. data/lib/project_types/extension/messages/messages.rb +3 -0
  47. data/lib/project_types/extension/models/development_server.rb +74 -0
  48. data/lib/project_types/extension/models/development_server_requirements.rb +36 -0
  49. data/lib/project_types/extension/models/lazy_specification_handler.rb +1 -1
  50. data/lib/project_types/extension/models/server_config/base.rb +31 -0
  51. data/lib/project_types/extension/models/server_config/development.rb +23 -0
  52. data/lib/project_types/extension/models/server_config/development_entries.rb +38 -0
  53. data/lib/project_types/extension/models/server_config/development_renderer.rb +30 -0
  54. data/lib/project_types/extension/models/server_config/extension.rb +35 -0
  55. data/lib/project_types/extension/models/server_config/root.rb +18 -0
  56. data/lib/project_types/extension/models/server_config/user.rb +10 -0
  57. data/lib/project_types/extension/models/specification.rb +1 -1
  58. data/lib/project_types/extension/models/specification_handlers/checkout_ui_extension.rb +1 -1
  59. data/lib/project_types/extension/models/specification_handlers/default.rb +10 -2
  60. data/lib/project_types/extension/models/specification_handlers/theme_app_extension.rb +1 -1
  61. data/lib/project_types/extension/models/specifications.rb +4 -4
  62. data/lib/project_types/extension/tasks/choose_next_available_port.rb +2 -2
  63. data/lib/project_types/extension/tasks/configure_features.rb +1 -1
  64. data/lib/project_types/extension/tasks/configure_options.rb +1 -1
  65. data/lib/project_types/extension/tasks/converters/product_converter.rb +1 -1
  66. data/lib/project_types/extension/tasks/create_extension.rb +2 -2
  67. data/lib/project_types/extension/tasks/fetch_specifications.rb +2 -2
  68. data/lib/project_types/extension/tasks/find_npm_packages.rb +3 -3
  69. data/lib/project_types/extension/tasks/get_app.rb +2 -2
  70. data/lib/project_types/extension/tasks/get_apps.rb +2 -2
  71. data/lib/project_types/extension/tasks/get_extensions.rb +2 -2
  72. data/lib/project_types/extension/tasks/get_product.rb +2 -2
  73. data/lib/project_types/extension/tasks/run_extension_command.rb +65 -0
  74. data/lib/project_types/extension/tasks/update_draft.rb +2 -2
  75. data/lib/project_types/node/cli.rb +3 -3
  76. data/lib/project_types/node/commands/connect.rb +4 -4
  77. data/lib/project_types/node/commands/create.rb +10 -14
  78. data/lib/project_types/node/commands/deploy/heroku.rb +4 -4
  79. data/lib/project_types/node/commands/deploy.rb +3 -3
  80. data/lib/project_types/node/commands/generate.rb +2 -2
  81. data/lib/project_types/node/commands/open.rb +3 -3
  82. data/lib/project_types/node/commands/serve.rb +7 -7
  83. data/lib/project_types/node/commands/tunnel.rb +6 -6
  84. data/lib/project_types/node/forms/create.rb +3 -3
  85. data/lib/project_types/php/cli.rb +27 -0
  86. data/lib/project_types/php/commands/connect.rb +19 -0
  87. data/lib/project_types/php/commands/create.rb +143 -0
  88. data/lib/project_types/php/commands/deploy/heroku.rb +129 -0
  89. data/lib/project_types/php/commands/deploy.rb +32 -0
  90. data/lib/project_types/php/commands/open.rb +16 -0
  91. data/lib/project_types/php/commands/serve.rb +51 -0
  92. data/lib/project_types/php/commands/tunnel.rb +37 -0
  93. data/lib/project_types/php/forms/create.rb +45 -0
  94. data/lib/project_types/php/messages/messages.rb +191 -0
  95. data/lib/project_types/rails/cli.rb +3 -3
  96. data/lib/project_types/rails/commands/connect.rb +4 -4
  97. data/lib/project_types/rails/commands/create.rb +12 -16
  98. data/lib/project_types/rails/commands/deploy/heroku.rb +4 -4
  99. data/lib/project_types/rails/commands/deploy.rb +3 -3
  100. data/lib/project_types/rails/commands/generate/webhook.rb +3 -3
  101. data/lib/project_types/rails/commands/generate.rb +3 -3
  102. data/lib/project_types/rails/commands/open.rb +3 -3
  103. data/lib/project_types/rails/commands/serve.rb +8 -8
  104. data/lib/project_types/rails/commands/tunnel.rb +6 -6
  105. data/lib/project_types/rails/forms/create.rb +3 -3
  106. data/lib/project_types/rails/gem.rb +1 -1
  107. data/lib/project_types/rails/ruby.rb +1 -1
  108. data/lib/project_types/script/cli.rb +12 -3
  109. data/lib/project_types/script/commands/create.rb +2 -2
  110. data/lib/project_types/script/commands/push.rb +2 -2
  111. data/lib/project_types/script/forms/create.rb +1 -1
  112. data/lib/project_types/script/graphql/app_script_set.graphql +40 -0
  113. data/lib/project_types/script/graphql/app_script_update_or_create.graphql +0 -44
  114. data/lib/project_types/script/graphql/module_upload_url_generate.graphql +9 -0
  115. data/lib/project_types/script/layers/application/extension_points.rb +2 -2
  116. data/lib/project_types/script/layers/application/push_script.rb +13 -1
  117. data/lib/project_types/script/layers/domain/push_package.rb +1 -14
  118. data/lib/project_types/script/layers/domain/script_project.rb +2 -2
  119. data/lib/project_types/script/layers/infrastructure/api_clients/partners_proxy_api_client.rb +55 -0
  120. data/lib/project_types/script/layers/infrastructure/api_clients/script_service_api_client.rb +35 -0
  121. data/lib/project_types/script/layers/infrastructure/command_runner.rb +1 -1
  122. data/lib/project_types/script/layers/infrastructure/errors.rb +2 -0
  123. data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb +2 -2
  124. data/lib/project_types/script/layers/infrastructure/languages/rust_project_creator.rb +1 -1
  125. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +1 -2
  126. data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +5 -5
  127. data/lib/project_types/script/layers/infrastructure/script_service.rb +28 -97
  128. data/lib/project_types/script/layers/infrastructure/script_uploader.rb +27 -0
  129. data/lib/project_types/script/layers/infrastructure/service_locator.rb +20 -0
  130. data/lib/project_types/script/messages/messages.rb +3 -0
  131. data/lib/project_types/script/tasks/ensure_env.rb +7 -7
  132. data/lib/project_types/script/ui/error_handler.rb +79 -74
  133. data/lib/project_types/script/ui/printing_spinner.rb +1 -1
  134. data/lib/project_types/theme/cli.rb +3 -3
  135. data/lib/project_types/theme/commands/check.rb +3 -3
  136. data/lib/project_types/theme/commands/delete.rb +7 -7
  137. data/lib/project_types/theme/commands/init.rb +3 -3
  138. data/lib/project_types/theme/commands/language_server.rb +2 -2
  139. data/lib/project_types/theme/commands/package.rb +2 -2
  140. data/lib/project_types/theme/commands/publish.rb +5 -5
  141. data/lib/project_types/theme/commands/pull.rb +15 -9
  142. data/lib/project_types/theme/commands/push.rb +18 -12
  143. data/lib/project_types/theme/commands/serve.rb +4 -4
  144. data/lib/project_types/theme/forms/confirm_store.rb +1 -1
  145. data/lib/project_types/theme/forms/select.rb +2 -2
  146. data/lib/{shopify-cli → shopify_cli}/admin_api/populate_resource_command.rb +3 -3
  147. data/lib/{shopify-cli → shopify_cli}/admin_api/schema.rb +4 -4
  148. data/lib/{shopify-cli → shopify_cli}/admin_api.rb +27 -27
  149. data/lib/{shopify-cli → shopify_cli}/api.rb +8 -8
  150. data/lib/{shopify-cli → shopify_cli}/command.rb +3 -3
  151. data/lib/{shopify-cli → shopify_cli}/commands/config.rb +14 -14
  152. data/lib/{shopify-cli → shopify_cli}/commands/help.rb +4 -4
  153. data/lib/{shopify-cli → shopify_cli}/commands/login.rb +7 -7
  154. data/lib/shopify_cli/commands/logout.rb +39 -0
  155. data/lib/{shopify-cli → shopify_cli}/commands/populate/customer.rb +4 -4
  156. data/lib/{shopify-cli → shopify_cli}/commands/populate/draft_order.rb +4 -4
  157. data/lib/{shopify-cli → shopify_cli}/commands/populate/product.rb +4 -4
  158. data/lib/shopify_cli/commands/populate.rb +23 -0
  159. data/lib/shopify_cli/commands/store.rb +15 -0
  160. data/lib/{shopify-cli → shopify_cli}/commands/switch.rb +5 -5
  161. data/lib/{shopify-cli → shopify_cli}/commands/system.rb +10 -10
  162. data/lib/shopify_cli/commands/version.rb +15 -0
  163. data/lib/{shopify-cli → shopify_cli}/commands/whoami.rb +7 -7
  164. data/lib/shopify_cli/commands.rb +34 -0
  165. data/lib/{shopify-cli → shopify_cli}/connect.rb +3 -3
  166. data/lib/shopify_cli/constants.rb +26 -0
  167. data/lib/{shopify-cli → shopify_cli}/context.rb +6 -6
  168. data/lib/{shopify-cli → shopify_cli}/core/entry_point.rb +7 -7
  169. data/lib/{shopify-cli → shopify_cli}/core/executor.rb +3 -3
  170. data/lib/{shopify-cli → shopify_cli}/core/finalize.rb +1 -1
  171. data/lib/{shopify-cli → shopify_cli}/core/help_resolver.rb +2 -2
  172. data/lib/{shopify-cli → shopify_cli}/core/monorail.rb +8 -8
  173. data/lib/shopify_cli/core.rb +8 -0
  174. data/lib/{shopify-cli → shopify_cli}/db.rb +8 -8
  175. data/lib/shopify_cli/environment.rb +60 -0
  176. data/lib/{shopify-cli → shopify_cli}/feature.rb +8 -8
  177. data/lib/{shopify-cli → shopify_cli}/form.rb +2 -2
  178. data/lib/{shopify-cli → shopify_cli}/git.rb +8 -8
  179. data/lib/{shopify-cli → shopify_cli}/helpers/haikunator.rb +1 -1
  180. data/lib/shopify_cli/helpers.rb +5 -0
  181. data/lib/{shopify-cli → shopify_cli}/heroku.rb +38 -13
  182. data/lib/{shopify-cli → shopify_cli}/http_request.rb +1 -1
  183. data/lib/{shopify-cli → shopify_cli}/identity_auth/servlet.rb +1 -1
  184. data/lib/{shopify-cli → shopify_cli}/identity_auth.rb +24 -31
  185. data/lib/{shopify-cli → shopify_cli}/js_deps.rb +7 -7
  186. data/lib/{shopify-cli → shopify_cli}/js_system.rb +10 -10
  187. data/lib/{shopify-cli → shopify_cli}/lazy_delegator.rb +2 -2
  188. data/lib/{shopify-cli → shopify_cli}/messages/messages.rb +17 -1
  189. data/lib/{shopify-cli → shopify_cli}/method_object.rb +4 -4
  190. data/lib/{shopify-cli → shopify_cli}/options.rb +1 -1
  191. data/lib/{shopify-cli → shopify_cli}/packager.rb +8 -8
  192. data/lib/{shopify-cli → shopify_cli}/partners_api/organizations.rb +1 -1
  193. data/lib/{shopify-cli → shopify_cli}/partners_api.rb +16 -40
  194. data/lib/shopify_cli/php_deps.rb +102 -0
  195. data/lib/{shopify-cli → shopify_cli}/process_supervision.rb +23 -21
  196. data/lib/{shopify-cli → shopify_cli}/project.rb +15 -15
  197. data/lib/{shopify-cli → shopify_cli}/project_commands.rb +3 -3
  198. data/lib/{shopify-cli → shopify_cli}/project_type.rb +5 -5
  199. data/lib/{shopify-cli → shopify_cli}/resolve_constant.rb +5 -5
  200. data/lib/{shopify-cli → shopify_cli}/resources/env_file.rb +1 -1
  201. data/lib/shopify_cli/resources.rb +5 -0
  202. data/lib/{shopify-cli → shopify_cli}/result.rb +11 -11
  203. data/lib/{shopify-cli → shopify_cli}/shopifolk.rb +6 -6
  204. data/lib/{shopify-cli → shopify_cli}/sub_command.rb +1 -1
  205. data/lib/{shopify-cli → shopify_cli}/task.rb +1 -1
  206. data/lib/{shopify-cli → shopify_cli}/tasks/confirm_store.rb +3 -3
  207. data/lib/{shopify-cli → shopify_cli}/tasks/create_api_client.rb +4 -4
  208. data/lib/shopify_cli/tasks/ensure_authenticated.rb +13 -0
  209. data/lib/{shopify-cli → shopify_cli}/tasks/ensure_dev_store.rb +5 -5
  210. data/lib/{shopify-cli → shopify_cli}/tasks/ensure_env.rb +3 -3
  211. data/lib/{shopify-cli → shopify_cli}/tasks/ensure_loopback_url.rb +4 -4
  212. data/lib/{shopify-cli → shopify_cli}/tasks/ensure_project_type.rb +3 -3
  213. data/lib/{shopify-cli → shopify_cli}/tasks/select_org_and_shop.rb +8 -8
  214. data/lib/{shopify-cli → shopify_cli}/tasks/update_dashboard_urls.rb +6 -6
  215. data/lib/{shopify-cli → shopify_cli}/tasks.rb +10 -10
  216. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/certificate_manager.rb +5 -5
  217. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/header_hash.rb +5 -1
  218. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/hot-reload.js +0 -0
  219. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/hot_reload.rb +5 -6
  220. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/local_assets.rb +1 -1
  221. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/proxy.rb +15 -3
  222. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/sse.rb +1 -1
  223. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/watcher.rb +1 -1
  224. data/lib/{shopify-cli → shopify_cli}/theme/dev_server/web_server.rb +1 -1
  225. data/lib/{shopify-cli → shopify_cli}/theme/dev_server.rb +3 -3
  226. data/lib/shopify_cli/theme/development_theme.rb +83 -0
  227. data/lib/{shopify-cli → shopify_cli}/theme/file.rb +12 -4
  228. data/lib/{shopify-cli → shopify_cli}/theme/ignore_filter.rb +8 -1
  229. data/lib/{shopify-cli → shopify_cli}/theme/mime_type.rb +1 -1
  230. data/lib/{shopify-cli → shopify_cli}/theme/syncer.rb +7 -7
  231. data/lib/{shopify-cli → shopify_cli}/theme/theme.rb +4 -4
  232. data/lib/{shopify-cli → shopify_cli}/transform_data_structure.rb +4 -4
  233. data/lib/{shopify-cli → shopify_cli}/tunnel.rb +14 -14
  234. data/lib/shopify_cli/version.rb +3 -0
  235. data/lib/shopify_cli.rb +52 -49
  236. data/shopify-cli.gemspec +5 -5
  237. metadata +130 -95
  238. data/.github/workflows/build.yml +0 -28
  239. data/lib/shopify-cli/commands/logout.rb +0 -39
  240. data/lib/shopify-cli/commands/populate.rb +0 -23
  241. data/lib/shopify-cli/commands/store.rb +0 -15
  242. data/lib/shopify-cli/commands/version.rb +0 -15
  243. data/lib/shopify-cli/commands.rb +0 -34
  244. data/lib/shopify-cli/core.rb +0 -8
  245. data/lib/shopify-cli/helpers.rb +0 -5
  246. data/lib/shopify-cli/resources.rb +0 -5
  247. data/lib/shopify-cli/tasks/ensure_authenticated.rb +0 -13
  248. data/lib/shopify-cli/theme/development_theme.rb +0 -69
  249. data/lib/shopify-cli/version.rb +0 -3
@@ -11,7 +11,7 @@ module Extension
11
11
  def call(context, identifier, directory_name, js_system)
12
12
  step_result = step.call(context, identifier, directory_name, js_system)
13
13
  can_fail? ? step_result : true
14
- rescue ShopifyCli::Abort => e
14
+ rescue ShopifyCLI::Abort => e
15
15
  context.puts(e.message)
16
16
  false
17
17
  rescue StandardError => e
@@ -18,7 +18,7 @@ module Extension
18
18
  def self.clone_template(git_template)
19
19
  ArgoSetupStep.default do |context, _identifier, directory_name, _js_system|
20
20
  begin
21
- ShopifyCli::Git.clone(git_template, directory_name, ctx: context)
21
+ ShopifyCLI::Git.clone(git_template, directory_name, ctx: context)
22
22
  context.root = File.join(context.root, directory_name)
23
23
  rescue StandardError
24
24
  context.puts("{{x}} Unable to clone the repository.")
@@ -28,7 +28,7 @@ module Extension
28
28
 
29
29
  def self.install_dependencies
30
30
  ArgoSetupStep.default do |context, _identifier, _directory_name, js_system|
31
- ShopifyCli::JsDeps.new(ctx: context, system: js_system).install
31
+ ShopifyCLI::JsDeps.new(ctx: context, system: js_system).install
32
32
  end
33
33
  end
34
34
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Extension
4
4
  module Forms
5
- class Connect < ShopifyCli::Form
5
+ class Connect < ShopifyCLI::Form
6
6
  attr_reader :registration, :app
7
7
 
8
8
  flag_arguments :type
@@ -19,7 +19,7 @@ module Extension
19
19
  end
20
20
 
21
21
  def ask
22
- ShopifyCli::Result.wrap(ExtensionProjectDetails.new)
22
+ ShopifyCLI::Result.wrap(ExtensionProjectDetails.new)
23
23
  .then(&Questions::AskRegistration.new(ctx: ctx, type: type))
24
24
  .unwrap { |e| raise e }
25
25
  .tap do |project_details|
@@ -2,8 +2,8 @@
2
2
 
3
3
  module Extension
4
4
  module Forms
5
- class Create < ShopifyCli::Form
6
- flag_arguments :name, :type, :api_key
5
+ class Create < ShopifyCLI::Form
6
+ flag_arguments :name, :type, :api_key, :template
7
7
 
8
8
  attr_reader :app
9
9
 
@@ -13,6 +13,7 @@ module Extension
13
13
  property :app, accepts: Models::App
14
14
  property :name, accepts: String
15
15
  property :type, accepts: Models::SpecificationHandlers::Default
16
+ property :template, accepts: String
16
17
 
17
18
  def complete?
18
19
  !!(app && name && type)
@@ -20,9 +21,10 @@ module Extension
20
21
  end
21
22
 
22
23
  def ask
23
- ShopifyCli::Result.wrap(ExtensionProjectDetails.new)
24
+ ShopifyCLI::Result.wrap(ExtensionProjectDetails.new)
24
25
  .then(&Questions::AskApp.new(ctx: ctx, api_key: api_key))
25
26
  .then(&Questions::AskType.new(ctx: ctx, type: type))
27
+ .then(&Questions::AskTemplate.new(ctx: ctx))
26
28
  .then(&Questions::AskName.new(ctx: ctx, name: name))
27
29
  .unwrap { |e| raise e }
28
30
  .tap do |project_details|
@@ -30,6 +32,7 @@ module Extension
30
32
 
31
33
  self.app = project_details.app
32
34
  self.type = project_details.type
35
+ self.template = project_details.template
33
36
  self.name = project_details.name
34
37
  end
35
38
  end
@@ -2,7 +2,7 @@ module Extension
2
2
  module Forms
3
3
  module Questions
4
4
  class AskApp
5
- include ShopifyCli::MethodObject
5
+ include ShopifyCLI::MethodObject
6
6
 
7
7
  property! :ctx
8
8
  property :api_key
@@ -45,7 +45,7 @@ module Extension
45
45
  def abort_no_apps
46
46
  ctx.puts(@ctx.message("create.no_apps"))
47
47
  ctx.puts(@ctx.message("create.learn_about_apps"))
48
- raise ShopifyCli::AbortSilent
48
+ raise ShopifyCLI::AbortSilent
49
49
  end
50
50
  end
51
51
  end
@@ -2,7 +2,7 @@ module Extension
2
2
  module Forms
3
3
  module Questions
4
4
  class AskName
5
- include ShopifyCli::MethodObject
5
+ include ShopifyCLI::MethodObject
6
6
 
7
7
  property! :ctx
8
8
  property :name
@@ -4,7 +4,7 @@ module Extension
4
4
  module Forms
5
5
  module Questions
6
6
  class AskRegistration
7
- include ShopifyCli::MethodObject
7
+ include ShopifyCLI::MethodObject
8
8
 
9
9
  property! :ctx
10
10
  property! :type
@@ -43,7 +43,7 @@ module Extension
43
43
  def abort_no_registrations
44
44
  ctx.puts(@ctx.message("connect.no_extensions", type))
45
45
  ctx.puts(@ctx.message("connect.learn_about_extensions"))
46
- raise ShopifyCli::AbortSilent
46
+ raise ShopifyCLI::AbortSilent
47
47
  end
48
48
  end
49
49
  end
@@ -0,0 +1,44 @@
1
+ module Extension
2
+ module Forms
3
+ module Questions
4
+ class AskTemplate
5
+ include ShopifyCLI::MethodObject
6
+
7
+ TEMPLATE_REQUIRED_TYPES = [
8
+ "checkout_ui_extension",
9
+ ]
10
+
11
+ property! :ctx
12
+ property :prompt,
13
+ accepts: ->(prompt) { prompt.respond_to?(:call) },
14
+ default: -> { CLI::UI::Prompt.method(:ask) }
15
+
16
+ def call(project_details)
17
+ return project_details unless template_required?(project_details)
18
+ project_details.template = choose_interactively
19
+ project_details
20
+ end
21
+
22
+ private
23
+
24
+ def template_required?(project_details)
25
+ return false unless extension_server_beta?
26
+ type = project_details&.type&.identifier
27
+ TEMPLATE_REQUIRED_TYPES.include?(type.downcase)
28
+ end
29
+
30
+ def extension_server_beta?
31
+ ShopifyCLI::Shopifolk.check && ShopifyCLI::Feature.enabled?(:extension_server_beta)
32
+ end
33
+
34
+ def choose_interactively
35
+ prompt.call(ctx.message("create.ask_template")) do |handler|
36
+ Models::ServerConfig::Development::VALID_TEMPLATES.each do |template|
37
+ handler.option(template) { template }
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -2,7 +2,7 @@ module Extension
2
2
  module Forms
3
3
  module Questions
4
4
  class AskType
5
- include ShopifyCli::MethodObject
5
+ include ShopifyCLI::MethodObject
6
6
 
7
7
  property! :ctx
8
8
  property :type
@@ -39,7 +39,7 @@ module Extension
39
39
 
40
40
  def abort_due_to_missing_specifications
41
41
  ctx.puts(@ctx.message("create.no_available_extensions"))
42
- raise ShopifyCli::AbortSilent
42
+ raise ShopifyCLI::AbortSilent
43
43
  end
44
44
  end
45
45
  end
@@ -15,9 +15,9 @@ module Extension
15
15
  end
16
16
 
17
17
  def self.load_current_type_messages
18
- return unless ShopifyCli::Project.has_current?
18
+ return unless ShopifyCLI::Project.has_current?
19
19
  messages_for_type(
20
- ShopifyCli::Project.current.config[Extension::ExtensionProjectKeys::SPECIFICATION_IDENTIFIER_KEY]
20
+ ShopifyCLI::Project.current.config[Extension::ExtensionProjectKeys::SPECIFICATION_IDENTIFIER_KEY]
21
21
  )
22
22
  end
23
23
 
@@ -45,6 +45,7 @@ module Extension
45
45
  "or try creating a new app using {{command:shopify [node|rails] create}}.",
46
46
  loading_apps: "Loading your apps…",
47
47
  no_available_extensions: "{{x}} There are no available extensions for this app.",
48
+ ask_template: "Select a template to use for your extension",
48
49
  },
49
50
  connect: {
50
51
  connected: "Project now connected to {{green:%s: %s}}",
@@ -67,6 +68,8 @@ module Extension
67
68
  HELP
68
69
  frame_title: "Building extension with: %s…",
69
70
  build_failure_message: "Failed to build extension code.",
71
+ build_success_message: "Build was successful!",
72
+ directory_not_found: "Build directory not found.",
70
73
  },
71
74
  register: {
72
75
  help: <<~HELP,
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Models
5
+ class DevelopmentServer
6
+ class DevelopmentServerError < StandardError; end
7
+
8
+ include SmartProperties
9
+
10
+ EXECUTABLE_DIRECTORY = File.join(ShopifyCLI::ROOT, "ext", "shopify-extensions")
11
+
12
+ property :executable, converts: :to_s
13
+
14
+ def executable
15
+ super || begin
16
+ case RbConfig::CONFIG.fetch("host_os")
17
+ when /(linux)|(darwin)/
18
+ File.join(EXECUTABLE_DIRECTORY, "shopify-extensions")
19
+ else
20
+ File.join(EXECUTABLE_DIRECTORY, "shopify-extensions.exe")
21
+ end
22
+ end
23
+ end
24
+
25
+ def create(server_config)
26
+ CLI::Kit::System.capture3(executable, "create", "-", stdin_data: server_config.to_yaml)
27
+ rescue StandardError => error
28
+ raise error
29
+ end
30
+
31
+ def build(server_config)
32
+ _, error, status = CLI::Kit::System.capture3(executable, "build", "-", stdin_data: server_config.to_yaml)
33
+ return if status.success?
34
+ raise DevelopmentServerError, error
35
+ end
36
+
37
+ def serve(context, server_config)
38
+ CLI::Kit::System.popen3(executable, "serve", "-") do |input, out, err, status|
39
+ context.puts("Sending configuration data …")
40
+ input << server_config.to_yaml
41
+ input.close
42
+
43
+ forward_output_to_user(out, err, context)
44
+
45
+ status.value
46
+ end
47
+ end
48
+
49
+ def version
50
+ raise NotImplementedError
51
+ end
52
+
53
+ private
54
+
55
+ def forward_output_to_user(out, err, ctx)
56
+ ctx.puts("Starting monitoring threads …")
57
+
58
+ Thread.new do
59
+ ctx.puts("Ready to process standard output")
60
+ while (line = out.gets)
61
+ ctx.puts(line)
62
+ end
63
+ end
64
+
65
+ Thread.new do
66
+ ctx.puts("Ready to process standard error")
67
+ while (error = err.gets)
68
+ ctx.puts(error)
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+ require "shopify_cli"
3
+
4
+ module Extension
5
+ module Models
6
+ class DevelopmentServerRequirements
7
+ SUPPORTED_EXTENSION_TYPES = [
8
+ "checkout_ui_extension",
9
+ ]
10
+
11
+ UNIX_NAME = "shopify-extensions"
12
+ WINDOWS_NAME = "shopify-extensions.exe"
13
+
14
+ class << self
15
+ def supported?(type)
16
+ binary_installed? && type_supported?(type) && beta_enabled?
17
+ end
18
+
19
+ private
20
+
21
+ def binary_installed?
22
+ extension_dir = File.join(ShopifyCLI::ROOT, "ext", "shopify-extensions")
23
+ File.exist?(File.join(extension_dir, UNIX_NAME)) || File.exist?(File.join(extension_dir, WINDOWS_NAME))
24
+ end
25
+
26
+ def type_supported?(type)
27
+ SUPPORTED_EXTENSION_TYPES.include?(type.downcase)
28
+ end
29
+
30
+ def beta_enabled?
31
+ ShopifyCLI::Shopifolk.check && ShopifyCLI::Feature.enabled?(:extension_server_beta)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,6 +1,6 @@
1
1
  module Extension
2
2
  module Models
3
- class LazySpecificationHandler < ShopifyCli::LazyDelegator
3
+ class LazySpecificationHandler < ShopifyCLI::LazyDelegator
4
4
  attr_reader :identifier
5
5
 
6
6
  def initialize(identifier, &specification_handler_initializer)
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Models
5
+ module ServerConfig
6
+ class Base
7
+ def to_h
8
+ to_hash
9
+ end
10
+
11
+ def to_hash
12
+ is_hashable = ->(obj) { obj.respond_to?(:to_hash) }
13
+ is_collection_of_hashables = ->(obj) { obj.is_a?(Enumerable) && obj.all?(&is_hashable) }
14
+
15
+ self.class.properties.each.reduce({}) do |data, (_, property)|
16
+ data.merge(property.name.to_s => send(property.reader).yield_self do |value|
17
+ case value
18
+ when is_collection_of_hashables
19
+ value.map { |element| element.to_hash.transform_keys(&:to_s) }
20
+ when is_hashable
21
+ value.to_hash.transform_keys(&:to_s)
22
+ else
23
+ value
24
+ end
25
+ end)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,23 @@
1
+ module Extension
2
+ module Models
3
+ module ServerConfig
4
+ class Development < Base
5
+ include SmartProperties
6
+ VALID_TEMPLATES = [
7
+ "javascript",
8
+ "javascript-react",
9
+ "typescript",
10
+ "typescript-react",
11
+ ]
12
+
13
+ CURRENT_DIRECTORY = "."
14
+
15
+ property :root_dir, accepts: String, default: CURRENT_DIRECTORY
16
+ property! :build_dir, accepts: String, default: "build"
17
+ property :template, accepts: VALID_TEMPLATES
18
+ property :renderer, accepts: ServerConfig::DevelopmentRenderer
19
+ property :entries, accepts: ServerConfig::DevelopmentEntries
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Models
5
+ module ServerConfig
6
+ class DevelopmentEntries < Base
7
+ include SmartProperties
8
+
9
+ JAVASCRIPT = "javascript"
10
+ JAVASCRIPT_REACT = "javascript-react"
11
+ TYPESCRIPT = "typescript"
12
+ TYPESCRIPT_REACT = "typescript-react"
13
+
14
+ VALID_ENTRY_POINTS = [
15
+ "src/index.js",
16
+ "src/index.jsx",
17
+ "src/index.ts",
18
+ "src/index.tsx",
19
+ ]
20
+
21
+ property! :main, accepts: VALID_ENTRY_POINTS
22
+
23
+ def self.find(template)
24
+ case template
25
+ when JAVASCRIPT
26
+ new(main: "src/index.js")
27
+ when JAVASCRIPT_REACT
28
+ new(main: "src/index.jsx")
29
+ when TYPESCRIPT
30
+ new(main: "src/index.ts")
31
+ when TYPESCRIPT_REACT
32
+ new(main: "src/index.tsx")
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Models
5
+ module ServerConfig
6
+ class DevelopmentRenderer < Base
7
+ include SmartProperties
8
+
9
+ VALID_RENDERERS = [
10
+ "@shopify/admin-ui-extensions",
11
+ "@shopify/post-purchase-ui-extensions",
12
+ "@shopify/checkout-ui-extensions",
13
+ ]
14
+
15
+ property! :name, accepts: VALID_RENDERERS
16
+
17
+ def self.find(type)
18
+ case type.downcase
19
+ when "admin_ui_extension"
20
+ new(name: "@shopify/admin-ui-extensions")
21
+ when "checkout_ui_extension"
22
+ new(name: "@shopify/checkout-ui-extensions")
23
+ when "checkout_post_purchase"
24
+ new(name: "@shopify/post-purchase-ui-extensions")
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,35 @@
1
+ require "securerandom"
2
+
3
+ module Extension
4
+ module Models
5
+ module ServerConfig
6
+ class Extension < Base
7
+ include SmartProperties
8
+ property! :uuid, accepts: String
9
+ property! :type, accepts: String
10
+ property! :user, accepts: ServerConfig::User
11
+ property! :development, accepts: ServerConfig::Development
12
+
13
+ def self.build(uuid: "", template:, type:, root_dir:)
14
+ renderer = ServerConfig::DevelopmentRenderer.find(type)
15
+ entry = ServerConfig::DevelopmentEntries.find(template)
16
+ new(
17
+ uuid: uuid.empty? ? generate_dev_uuid : uuid,
18
+ type: type.downcase,
19
+ user: ServerConfig::User.new,
20
+ development: ServerConfig::Development.new(
21
+ root_dir: root_dir,
22
+ template: template,
23
+ renderer: renderer,
24
+ entries: entry
25
+ )
26
+ )
27
+ end
28
+
29
+ def self.generate_dev_uuid
30
+ "dev-#{SecureRandom.uuid}"
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Models
5
+ module ServerConfig
6
+ class Root < Base
7
+ include SmartProperties
8
+
9
+ property! :port, accepts: Integer, default: 39351
10
+ property! :extensions, accepts: Array, default: -> { [] }
11
+
12
+ def to_yaml
13
+ to_h.to_yaml.gsub("---\n", "")
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,10 @@
1
+ module Extension
2
+ module Models
3
+ module ServerConfig
4
+ class User < Base
5
+ include SmartProperties
6
+ property! :metafields, accepts: Array, default: -> { [] }
7
+ end
8
+ end
9
+ end
10
+ end
@@ -18,7 +18,7 @@ module Extension
18
18
  def self.build(feature_set_attributes)
19
19
  feature_set_attributes.each_with_object(OpenStruct.new) do |(identifier, feature_attributes), feature_set|
20
20
  next if feature_attributes.nil?
21
- feature_set[identifier] = ShopifyCli::ResolveConstant
21
+ feature_set[identifier] = ShopifyCLI::ResolveConstant
22
22
  .call(identifier, namespace: Features)
23
23
  .rescue { OpenStruct }
24
24
  .then { |c| c.new(**feature_attributes) }
@@ -4,7 +4,7 @@ module Extension
4
4
  module Models
5
5
  module SpecificationHandlers
6
6
  class CheckoutUiExtension < Default
7
- PERMITTED_CONFIG_KEYS = [:metafields, :extension_points]
7
+ PERMITTED_CONFIG_KEYS = [:extension_points, :metafields, :name]
8
8
 
9
9
  def config(context)
10
10
  {
@@ -43,10 +43,12 @@ module Extension
43
43
  end
44
44
 
45
45
  def choose_port?(context)
46
+ return true if supports_development_server?
46
47
  argo_runtime(context).supports?(:port)
47
48
  end
48
49
 
49
50
  def establish_tunnel?(context)
51
+ return true if supports_development_server?
50
52
  argo_runtime(context).supports?(:public_url)
51
53
  end
52
54
 
@@ -66,6 +68,8 @@ module Extension
66
68
  end
67
69
 
68
70
  def argo_runtime(context)
71
+ return if supports_development_server?
72
+
69
73
  @argo_runtime ||= Features::ArgoRuntime.find(
70
74
  cli_package: cli_package(context),
71
75
  identifier: identifier
@@ -76,7 +80,7 @@ module Extension
76
80
  cli_package_name = specification.features.argo&.cli_package_name
77
81
  return unless cli_package_name
78
82
 
79
- js_system = ShopifyCli::JsSystem.new(ctx: context)
83
+ js_system = ShopifyCLI::JsSystem.new(ctx: context)
80
84
  Tasks::FindNpmPackages.exactly_one_of(cli_package_name, js_system: js_system)
81
85
  .unwrap { |_e| context.abort(context.message("errors.package_not_found", cli_package_name)) }
82
86
  end
@@ -87,7 +91,7 @@ module Extension
87
91
  if (str = messages.dig(*key_parts))
88
92
  str % params
89
93
  else
90
- ShopifyCli::Context.message(key, *params)
94
+ ShopifyCLI::Context.message(key, *params)
91
95
  end
92
96
  end
93
97
 
@@ -118,6 +122,10 @@ module Extension
118
122
  def messages
119
123
  @messages ||= Messages::TYPES[identifier.downcase.to_sym] || {}
120
124
  end
125
+
126
+ def supports_development_server?
127
+ Models::DevelopmentServerRequirements.supported?(identifier)
128
+ end
121
129
  end
122
130
  end
123
131
  end
@@ -15,7 +15,7 @@ module Extension
15
15
  context.root = File.join(context.root, directory_name)
16
16
 
17
17
  if getting_started
18
- ShopifyCli::Git.clone("https://github.com/Shopify/theme-extension-getting-started", context.root)
18
+ ShopifyCLI::Git.clone("https://github.com/Shopify/theme-extension-getting-started", context.root)
19
19
  context.rm_r(".git")
20
20
  else
21
21
  FileUtils.makedirs(SUPPORTED_BUCKETS.map { |b| File.join(context.root, b) })
@@ -5,7 +5,7 @@ module Extension
5
5
 
6
6
  property! :custom_handler_root,
7
7
  accepts: ->(d) { File.directory?(d) },
8
- default: -> { File.expand_path("lib/project_types/extension/models/specification_handlers", ShopifyCli::ROOT) }
8
+ default: -> { File.expand_path("lib/project_types/extension/models/specification_handlers", ShopifyCLI::ROOT) }
9
9
 
10
10
  property! :custom_handler_namespace,
11
11
  accepts: ->(m) { m.respond_to?(:const_get) },
@@ -39,9 +39,9 @@ module Extension
39
39
  private
40
40
 
41
41
  def fetch_specifications_and_build_handlers
42
- ShopifyCli::Result
42
+ ShopifyCLI::Result
43
43
  .call(&fetch_specifications)
44
- .map(&ShopifyCli::TransformDataStructure.new(symbolize_keys: true, underscore_keys: true))
44
+ .map(&ShopifyCLI::TransformDataStructure.new(symbolize_keys: true, underscore_keys: true))
45
45
  .then(&method(:select_cli_extensions))
46
46
  .then(&Tasks::ConfigureFeatures)
47
47
  .then(&Tasks::ConfigureOptions)
@@ -61,7 +61,7 @@ module Extension
61
61
 
62
62
  def instantiate_specification_handlers(specifications)
63
63
  specifications.each_with_object({}) do |specification, handlers|
64
- ShopifyCli::ResolveConstant.call(specification.identifier, namespace: custom_handler_namespace)
64
+ ShopifyCLI::ResolveConstant.call(specification.identifier, namespace: custom_handler_namespace)
65
65
  .rescue { |error| error.is_a?(NameError) ? SpecificationHandlers::Default : raise(error) }
66
66
  .then { |handler_class| handler_class.new(specification) }
67
67
  .unwrap { |error| raise error }
@@ -5,11 +5,11 @@ require "socket"
5
5
  module Extension
6
6
  module Tasks
7
7
  class ChooseNextAvailablePort
8
- include ShopifyCli::MethodObject
8
+ include ShopifyCLI::MethodObject
9
9
 
10
10
  property! :from
11
11
  property! :to, default: -> { from + 10 }
12
- property! :host, default: "localhost"
12
+ property! :host, default: "127.0.0.1"
13
13
 
14
14
  def call
15
15
  available_port = port_range(from: from, to: to).find { |p| available?(host, p) }