shopify-cli 1.13.1 → 2.1.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 (200) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -1
  3. data/.github/CONTRIBUTING.md +7 -7
  4. data/.github/DESIGN.md +3 -3
  5. data/.github/workflows/build.yml +1 -1
  6. data/.gitignore +3 -0
  7. data/.rubocop.yml +3 -1
  8. data/.ruby-version +1 -1
  9. data/CHANGELOG.md +60 -26
  10. data/Gemfile +4 -0
  11. data/Gemfile.lock +32 -0
  12. data/LICENSE +4 -1
  13. data/README.md +94 -26
  14. data/RELEASING.md +31 -7
  15. data/Rakefile +2 -2
  16. data/SECURITY.md +1 -1
  17. data/THEMEKIT_MIGRATION.md +18 -0
  18. data/bin/load_shopify.rb +1 -1
  19. data/bin/shopify +3 -3
  20. data/dev.yml +1 -1
  21. data/docs/app/node/index.md +1 -1
  22. data/docs/app/rails/index.md +1 -1
  23. data/docs/core/index.md +1 -1
  24. data/docs/getting-started/index.md +1 -1
  25. data/docs/getting-started/install/index.md +1 -1
  26. data/docs/getting-started/migrate/index.md +1 -1
  27. data/docs/getting-started/uninstall/index.md +1 -1
  28. data/docs/getting-started/upgrade/index.md +1 -1
  29. data/docs/help/start-app/index.md +1 -1
  30. data/docs/index.md +1 -1
  31. data/ext/shopify-cli/extconf.rb +17 -5
  32. data/install.sh +1 -1
  33. data/lib/docgen/index_template.md.erb +2 -2
  34. data/lib/graphql/all_orgs_with_extensions.graphql +37 -0
  35. data/lib/graphql/api_versions.graphql +1 -1
  36. data/lib/graphql/find_organization.graphql +2 -1
  37. data/lib/project_types/extension/cli.rb +19 -15
  38. data/lib/project_types/extension/commands/build.rb +4 -5
  39. data/lib/project_types/extension/commands/check.rb +44 -0
  40. data/lib/project_types/extension/commands/connect.rb +35 -0
  41. data/lib/project_types/extension/commands/create.rb +12 -16
  42. data/lib/project_types/extension/commands/extension_command.rb +2 -2
  43. data/lib/project_types/extension/commands/info.rb +86 -0
  44. data/lib/project_types/extension/commands/push.rb +8 -7
  45. data/lib/project_types/extension/commands/register.rb +4 -5
  46. data/lib/project_types/extension/commands/serve.rb +5 -8
  47. data/lib/project_types/extension/commands/tunnel.rb +3 -1
  48. data/lib/project_types/extension/errors.rb +9 -0
  49. data/lib/project_types/extension/extension_project.rb +24 -1
  50. data/lib/project_types/extension/extension_project_keys.rb +1 -0
  51. data/lib/project_types/extension/features/argo.rb +6 -6
  52. data/lib/project_types/extension/features/argo_runtime.rb +22 -66
  53. data/lib/project_types/extension/features/argo_serve.rb +25 -18
  54. data/lib/project_types/extension/forms/connect.rb +42 -0
  55. data/lib/project_types/extension/forms/questions/ask_name.rb +14 -6
  56. data/lib/project_types/extension/forms/questions/ask_registration.rb +51 -0
  57. data/lib/project_types/extension/messages/messages.rb +84 -16
  58. data/lib/project_types/extension/models/specification.rb +1 -0
  59. data/lib/project_types/extension/models/specification_handlers/{checkout_argo_extension.rb → checkout_ui_extension.rb} +3 -1
  60. data/lib/project_types/extension/models/specification_handlers/default.rb +13 -3
  61. data/lib/project_types/extension/models/specification_handlers/theme_app_extension.rb +89 -0
  62. data/lib/project_types/extension/models/specifications.rb +1 -0
  63. data/lib/project_types/extension/tasks/configure_features.rb +6 -7
  64. data/lib/project_types/extension/tasks/configure_options.rb +20 -0
  65. data/lib/project_types/extension/tasks/get_extensions.rb +32 -0
  66. data/lib/project_types/node/cli.rb +9 -21
  67. data/lib/project_types/node/commands/connect.rb +8 -2
  68. data/lib/project_types/node/commands/create.rb +9 -5
  69. data/lib/project_types/node/commands/deploy.rb +15 -5
  70. data/lib/project_types/node/commands/deploy/heroku.rb +29 -29
  71. data/lib/project_types/node/commands/generate.rb +4 -2
  72. data/lib/project_types/node/commands/open.rb +4 -2
  73. data/lib/project_types/node/commands/serve.rb +3 -2
  74. data/lib/project_types/node/commands/tunnel.rb +4 -2
  75. data/lib/project_types/node/messages/messages.rb +47 -90
  76. data/lib/project_types/rails/cli.rb +9 -21
  77. data/lib/project_types/rails/commands/connect.rb +8 -2
  78. data/lib/project_types/rails/commands/create.rb +10 -6
  79. data/lib/project_types/rails/commands/deploy.rb +15 -5
  80. data/lib/project_types/rails/commands/deploy/heroku.rb +84 -82
  81. data/lib/project_types/rails/commands/generate.rb +15 -5
  82. data/lib/project_types/rails/commands/generate/webhook.rb +28 -26
  83. data/lib/project_types/rails/commands/open.rb +4 -2
  84. data/lib/project_types/rails/commands/serve.rb +3 -2
  85. data/lib/project_types/rails/commands/tunnel.rb +4 -2
  86. data/lib/project_types/rails/messages/messages.rb +72 -119
  87. data/lib/project_types/script/cli.rb +6 -8
  88. data/lib/project_types/script/commands/create.rb +3 -1
  89. data/lib/project_types/script/commands/push.rb +7 -4
  90. data/lib/project_types/script/graphql/app_script_update_or_create.graphql +9 -3
  91. data/lib/project_types/script/layers/application/create_script.rb +4 -3
  92. data/lib/project_types/script/layers/domain/errors.rb +6 -11
  93. data/lib/project_types/script/layers/domain/push_package.rb +4 -8
  94. data/lib/project_types/script/layers/domain/script_json.rb +32 -0
  95. data/lib/project_types/script/layers/domain/script_project.rb +1 -1
  96. data/lib/project_types/script/layers/infrastructure/errors.rb +13 -17
  97. data/lib/project_types/script/layers/infrastructure/languages/assemblyscript_project_creator.rb +29 -21
  98. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +2 -4
  99. data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +45 -34
  100. data/lib/project_types/script/layers/infrastructure/script_service.rb +37 -16
  101. data/lib/project_types/script/messages/messages.rb +64 -54
  102. data/lib/project_types/script/tasks/ensure_env.rb +3 -1
  103. data/lib/project_types/script/ui/error_handler.rb +32 -32
  104. data/lib/project_types/theme/cli.rb +16 -27
  105. data/lib/project_types/theme/commands/check.rb +33 -0
  106. data/lib/project_types/theme/commands/delete.rb +64 -0
  107. data/lib/project_types/theme/commands/init.rb +42 -0
  108. data/lib/project_types/theme/commands/language_server.rb +16 -0
  109. data/lib/project_types/theme/commands/package.rb +55 -0
  110. data/lib/project_types/theme/commands/publish.rb +43 -0
  111. data/lib/project_types/theme/commands/pull.rb +51 -0
  112. data/lib/project_types/theme/commands/push.rb +58 -32
  113. data/lib/project_types/theme/commands/serve.rb +8 -16
  114. data/lib/project_types/theme/forms/confirm_store.rb +15 -0
  115. data/lib/project_types/theme/forms/select.rb +59 -0
  116. data/lib/project_types/theme/messages/messages.rb +118 -103
  117. data/lib/project_types/theme/ui/sync_progress_bar.rb +20 -0
  118. data/lib/shopify-cli/admin_api.rb +57 -38
  119. data/lib/shopify-cli/admin_api/populate_resource_command.rb +6 -14
  120. data/lib/shopify-cli/admin_api/schema.rb +1 -10
  121. data/lib/shopify-cli/api.rb +29 -14
  122. data/lib/shopify-cli/command.rb +15 -3
  123. data/lib/shopify-cli/commands.rb +7 -2
  124. data/lib/shopify-cli/commands/help.rb +2 -29
  125. data/lib/shopify-cli/commands/login.rb +95 -0
  126. data/lib/shopify-cli/commands/logout.rb +24 -8
  127. data/lib/shopify-cli/commands/populate.rb +23 -0
  128. data/lib/{project_types/node → shopify-cli}/commands/populate/customer.rb +2 -8
  129. data/lib/{project_types/node → shopify-cli}/commands/populate/draft_order.rb +2 -2
  130. data/lib/{project_types/node → shopify-cli}/commands/populate/product.rb +2 -8
  131. data/lib/shopify-cli/commands/store.rb +15 -0
  132. data/lib/shopify-cli/commands/switch.rb +39 -0
  133. data/lib/shopify-cli/commands/system.rb +12 -0
  134. data/lib/shopify-cli/commands/whoami.rb +28 -0
  135. data/lib/shopify-cli/connect.rb +32 -0
  136. data/lib/shopify-cli/context.rb +65 -4
  137. data/lib/shopify-cli/core/entry_point.rb +3 -22
  138. data/lib/shopify-cli/core/monorail.rb +6 -2
  139. data/lib/shopify-cli/db.rb +4 -4
  140. data/lib/shopify-cli/http_request.rb +16 -0
  141. data/lib/shopify-cli/identity_auth.rb +282 -0
  142. data/lib/shopify-cli/{oauth → identity_auth}/servlet.rb +11 -12
  143. data/lib/shopify-cli/messages/messages.rb +140 -46
  144. data/lib/shopify-cli/packager.rb +5 -5
  145. data/lib/shopify-cli/partners_api.rb +21 -44
  146. data/lib/shopify-cli/partners_api/organizations.rb +8 -0
  147. data/lib/shopify-cli/project_commands.rb +16 -0
  148. data/lib/shopify-cli/project_type.rb +0 -31
  149. data/lib/shopify-cli/shopifolk.rb +8 -11
  150. data/lib/shopify-cli/sub_command.rb +1 -0
  151. data/lib/shopify-cli/tasks.rb +3 -0
  152. data/lib/shopify-cli/tasks/confirm_store.rb +18 -0
  153. data/lib/shopify-cli/tasks/create_api_client.rb +2 -2
  154. data/lib/shopify-cli/tasks/ensure_authenticated.rb +13 -0
  155. data/lib/shopify-cli/tasks/ensure_loopback_url.rb +1 -1
  156. data/lib/shopify-cli/tasks/ensure_project_type.rb +12 -0
  157. data/lib/shopify-cli/tasks/select_org_and_shop.rb +0 -3
  158. data/lib/shopify-cli/theme/dev_server.rb +98 -0
  159. data/lib/shopify-cli/theme/dev_server/certificate_manager.rb +79 -0
  160. data/lib/shopify-cli/theme/dev_server/header_hash.rb +94 -0
  161. data/lib/shopify-cli/theme/dev_server/hot-reload.js +93 -0
  162. data/lib/shopify-cli/theme/dev_server/hot_reload.rb +76 -0
  163. data/lib/shopify-cli/theme/dev_server/local_assets.rb +87 -0
  164. data/lib/shopify-cli/theme/dev_server/proxy.rb +205 -0
  165. data/lib/shopify-cli/theme/dev_server/sse.rb +75 -0
  166. data/lib/shopify-cli/theme/dev_server/watcher.rb +59 -0
  167. data/lib/shopify-cli/theme/dev_server/web_server.rb +140 -0
  168. data/lib/shopify-cli/theme/development_theme.rb +69 -0
  169. data/lib/shopify-cli/theme/file.rb +112 -0
  170. data/lib/shopify-cli/theme/ignore_filter.rb +109 -0
  171. data/lib/shopify-cli/theme/mime_type.rb +34 -0
  172. data/lib/shopify-cli/theme/syncer.rb +332 -0
  173. data/lib/shopify-cli/theme/theme.rb +204 -0
  174. data/lib/shopify-cli/tunnel.rb +1 -1
  175. data/lib/shopify-cli/version.rb +1 -1
  176. data/lib/shopify_cli.rb +18 -11
  177. data/shopify-cli.gemspec +12 -5
  178. data/shopify.fish +1 -1
  179. data/shopify.sh +1 -1
  180. metadata +92 -35
  181. data/.github/workflows/release.yml +0 -59
  182. data/lib/project_types/extension/features/argo_serve_options.rb +0 -42
  183. data/lib/project_types/node/commands/populate.rb +0 -23
  184. data/lib/project_types/rails/commands/populate.rb +0 -23
  185. data/lib/project_types/rails/commands/populate/customer.rb +0 -31
  186. data/lib/project_types/rails/commands/populate/draft_order.rb +0 -28
  187. data/lib/project_types/rails/commands/populate/product.rb +0 -30
  188. data/lib/project_types/script/layers/domain/config_ui.rb +0 -16
  189. data/lib/project_types/theme/commands/connect.rb +0 -54
  190. data/lib/project_types/theme/commands/create.rb +0 -48
  191. data/lib/project_types/theme/commands/deploy.rb +0 -38
  192. data/lib/project_types/theme/commands/generate.rb +0 -20
  193. data/lib/project_types/theme/commands/generate/env.rb +0 -79
  194. data/lib/project_types/theme/forms/connect.rb +0 -34
  195. data/lib/project_types/theme/forms/create.rb +0 -22
  196. data/lib/project_types/theme/tasks/ensure_themekit_installed.rb +0 -78
  197. data/lib/project_types/theme/themekit.rb +0 -113
  198. data/lib/shopify-cli/commands/connect.rb +0 -64
  199. data/lib/shopify-cli/commands/create.rb +0 -50
  200. data/lib/shopify-cli/oauth.rb +0 -198
@@ -19,14 +19,14 @@ module Extension
19
19
  YARN_RUN_SCRIPT_NAME = %w(build).freeze
20
20
  private_constant :YARN_INSTALL_COMMAND, :YARN_INSTALL_PARAMETERS, :YARN_RUN_COMMAND, :YARN_RUN_SCRIPT_NAME
21
21
 
22
- ARGO_CHECKOUT = "@shopify/argo-checkout"
23
- ARGO_ADMIN = "@shopify/argo-admin"
24
- ARGO_POST_PURCHASE = "@shopify/argo-post-purchase"
22
+ UI_EXTENSIONS_CHECKOUT = "@shopify/checkout-ui-extensions"
23
+ UI_EXTENSIONS_ADMIN = "@shopify/admin-ui-extensions"
24
+ UI_EXTENSIONS_POST_PURCHASE = "@shopify/post-purchase-ui-extensions"
25
25
 
26
26
  PACKAGE_NAMES = [
27
- ARGO_CHECKOUT,
28
- ARGO_ADMIN,
29
- ARGO_POST_PURCHASE,
27
+ UI_EXTENSIONS_CHECKOUT,
28
+ UI_EXTENSIONS_ADMIN,
29
+ UI_EXTENSIONS_POST_PURCHASE,
30
30
  ].freeze
31
31
 
32
32
  def create(directory_name, identifier, context)
@@ -3,88 +3,44 @@ module Extension
3
3
  class ArgoRuntime
4
4
  include SmartProperties
5
5
 
6
- ARGO_RUN_PACKAGE_NAME = "@shopify/argo-run"
7
- ARGO_ADMIN_CLI_PACKAGE_NAME = "@shopify/argo-admin-cli"
8
-
9
- ARGO_RUN_0_4_0 = Models::NpmPackage.new(name: "@shopify/argo-run", version: "0.4.0")
10
- ARGO_ADMIN_CLI_0_9_0 = Models::NpmPackage.new(name: "@shopify/argo-admin-cli", version: "0.9.0")
11
- ARGO_ADMIN_CLI_0_9_3 = Models::NpmPackage.new(name: "@shopify/argo-admin-cli", version: "0.9.3")
12
- ARGO_ADMIN_CLI_0_11_0 = Models::NpmPackage.new(name: "@shopify/argo-admin-cli", version: "0.11.0")
6
+ UI_EXTENSIONS_CHECKOUT_RUN = "@shopify/checkout-ui-extensions-run"
7
+ UI_EXTENSIONS_ADMIN_RUN = "@shopify/admin-ui-extensions-run"
8
+
9
+ ADMIN_RUN_FLAGS = [
10
+ :api_key,
11
+ :name,
12
+ :port,
13
+ :public_url,
14
+ :renderer_version,
15
+ :shop,
16
+ :uuid,
17
+ ]
18
+
19
+ CHECKOUT_RUN_FLAGS = [
20
+ :port,
21
+ :public_url,
22
+ ]
13
23
 
14
24
  property! :renderer, accepts: Models::NpmPackage
15
25
  property! :cli, accepts: Models::NpmPackage
16
26
 
17
- def accepts_port?
18
- case cli
19
- when admin?
20
- cli >= ARGO_ADMIN_CLI_0_11_0
21
- when checkout?
22
- cli >= ARGO_RUN_0_4_0
23
- end
24
- end
25
-
26
- def accepts_tunnel_url?
27
+ def supports?(flag)
27
28
  case cli
28
29
  when admin?
29
- cli >= ARGO_ADMIN_CLI_0_11_0
30
+ ADMIN_RUN_FLAGS.include?(flag.to_sym)
30
31
  when checkout?
31
- cli >= ARGO_RUN_0_4_0
32
- end
33
- end
34
-
35
- def accepts_uuid?
36
- case cli
37
- when admin?
38
- cli >= ARGO_ADMIN_CLI_0_11_0
39
- else
40
- false
41
- end
42
- end
43
-
44
- def accepts_argo_version?
45
- case cli
46
- when admin?
47
- cli >= ARGO_ADMIN_CLI_0_9_3
48
- else
49
- false
50
- end
51
- end
52
-
53
- def accepts_shop?
54
- case cli
55
- when admin?
56
- cli >= ARGO_ADMIN_CLI_0_11_0
57
- else
58
- false
59
- end
60
- end
61
-
62
- def accepts_api_key?
63
- case cli
64
- when admin?
65
- cli >= ARGO_ADMIN_CLI_0_11_0
66
- else
67
- false
68
- end
69
- end
70
-
71
- def accepts_name?
72
- case cli
73
- when admin?
74
- cli >= ARGO_ADMIN_CLI_0_9_0
75
- else
76
- false
32
+ CHECKOUT_RUN_FLAGS.include?(flag.to_sym)
77
33
  end
78
34
  end
79
35
 
80
36
  private
81
37
 
82
38
  def admin?
83
- ->(cli) { cli.name == ARGO_ADMIN_CLI_PACKAGE_NAME }
39
+ ->(cli) { cli.name == UI_EXTENSIONS_ADMIN_RUN }
84
40
  end
85
41
 
86
42
  def checkout?
87
- ->(cli) { cli.name == ARGO_RUN_PACKAGE_NAME }
43
+ ->(cli) { cli.name == UI_EXTENSIONS_CHECKOUT_RUN }
88
44
  end
89
45
  end
90
46
  end
@@ -3,25 +3,29 @@ module Extension
3
3
  class ArgoServe
4
4
  include SmartProperties
5
5
 
6
+ YARN_SERVE_COMMAND = %w(server)
7
+ NPM_SERVE_COMMAND = %w(run-script server)
8
+
6
9
  property! :specification_handler, accepts: Extension::Models::SpecificationHandlers::Default
7
10
  property! :argo_runtime, accepts: Features::ArgoRuntime
8
11
  property! :context, accepts: ShopifyCli::Context
9
12
  property! :port, accepts: Integer, default: 39351
10
- property :tunnel_url, accepts: String, default: ""
13
+ property :tunnel_url, accepts: String, default: nil
14
+ property! :js_system, accepts: ->(jss) { jss.respond_to?(:call) }, default: ShopifyCli::JsSystem
11
15
 
12
16
  def call
13
17
  validate_env!
14
18
 
15
19
  CLI::UI::Frame.open(context.message("serve.frame_title")) do
16
- success = call_js_system(yarn_command: yarn_serve_command, npm_command: npm_serve_command)
17
- context.abort(context.message("serve.serve_failure_message")) unless success
20
+ next if start_server
21
+ context.abort(context.message("serve.serve_failure_message"))
18
22
  end
19
23
  end
20
24
 
21
25
  private
22
26
 
23
- def call_js_system(yarn_command:, npm_command:)
24
- ShopifyCli::JsSystem.call(context, yarn: yarn_command, npm: npm_command)
27
+ def start_server
28
+ js_system.call(context, yarn: yarn_serve_command, npm: npm_serve_command)
25
29
  end
26
30
 
27
31
  def specification
@@ -36,23 +40,12 @@ module Extension
36
40
  specification.features.argo.required_fields
37
41
  end
38
42
 
39
- def serve_options
40
- @options ||= Features::ArgoServeOptions.new(
41
- argo_runtime: argo_runtime,
42
- port: port,
43
- context: context,
44
- required_fields: required_fields,
45
- renderer_package: renderer_package,
46
- public_url: tunnel_url
47
- )
48
- end
49
-
50
43
  def yarn_serve_command
51
- serve_options.yarn_serve_command
44
+ YARN_SERVE_COMMAND + options
52
45
  end
53
46
 
54
47
  def npm_serve_command
55
- serve_options.npm_serve_command
48
+ NPM_SERVE_COMMAND + ["--"] + options
56
49
  end
57
50
 
58
51
  def validate_env!
@@ -72,6 +65,20 @@ module Extension
72
65
 
73
66
  context.abort(context.message("serve.serve_missing_information"))
74
67
  end
68
+
69
+ def options
70
+ project = ExtensionProject.current
71
+
72
+ @serve_options ||= [].tap do |options|
73
+ options << "--port=#{port}" if argo_runtime.supports?(:port)
74
+ options << "--store=#{project.env.shop}" if argo_runtime.supports?(:shop)
75
+ options << "--apiKey=#{project.env.api_key}" if argo_runtime.supports?(:api_key)
76
+ options << "--rendererVersion=#{renderer_package.version}" if argo_runtime.supports?(:renderer_version)
77
+ options << "--uuid=#{project.registration_uuid}" if argo_runtime.supports?(:uuid)
78
+ options << "--publicUrl=#{tunnel_url}" if !tunnel_url.nil? && argo_runtime.supports?(:public_url)
79
+ options << "--name=#{project.title}" if argo_runtime.supports?(:name)
80
+ end
81
+ end
75
82
  end
76
83
  end
77
84
  end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Forms
5
+ class Connect < ShopifyCli::Form
6
+ attr_reader :registration, :app
7
+
8
+ flag_arguments :type
9
+
10
+ class ExtensionProjectDetails
11
+ include SmartProperties
12
+
13
+ property :registration, accepts: Models::Registration
14
+ property :app, accepts: Models::App
15
+
16
+ def complete?
17
+ !!(registration && app)
18
+ end
19
+ end
20
+
21
+ def ask
22
+ ShopifyCli::Result.wrap(ExtensionProjectDetails.new)
23
+ .then(&Questions::AskRegistration.new(ctx: ctx, type: type))
24
+ .unwrap { |e| raise e }
25
+ .tap do |project_details|
26
+ ctx.abort(ctx.message("connect.incomplete_configuration")) unless project_details.complete?
27
+
28
+ self.registration = project_details.registration
29
+ self.app = project_details.app
30
+ end
31
+ end
32
+
33
+ def directory_name
34
+ name.strip.gsub(/( )/, "_").downcase
35
+ end
36
+
37
+ private
38
+
39
+ attr_writer :registration, :app
40
+ end
41
+ end
42
+ end
@@ -11,17 +11,25 @@ module Extension
11
11
  default: -> { CLI::UI::Prompt.method(:ask) }
12
12
 
13
13
  def call(project_details)
14
- project_details.name = ask_with_reprompt(
15
- initial_value: name,
16
- break_condition: -> (current_name) { Models::Registration.valid_title?(current_name) },
17
- prompt_message: ctx.message("create.ask_name"),
18
- reprompt_message: ctx.message("create.invalid_name", Models::Registration::MAX_TITLE_LENGTH)
19
- )
14
+ if theme_app_extension?(project_details)
15
+ project_details.name = name || "theme-app-extension"
16
+ else
17
+ project_details.name = ask_with_reprompt(
18
+ initial_value: name,
19
+ break_condition: -> (current_name) { Models::Registration.valid_title?(current_name) },
20
+ prompt_message: ctx.message("create.ask_name"),
21
+ reprompt_message: ctx.message("create.invalid_name", Models::Registration::MAX_TITLE_LENGTH)
22
+ )
23
+ end
20
24
  project_details
21
25
  end
22
26
 
23
27
  private
24
28
 
29
+ def theme_app_extension?(project_details)
30
+ project_details&.type&.identifier == "THEME_APP_EXTENSION"
31
+ end
32
+
25
33
  def ask_with_reprompt(initial_value:, break_condition:, prompt_message:, reprompt_message:)
26
34
  value = initial_value
27
35
  reprompt = false
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Forms
5
+ module Questions
6
+ class AskRegistration
7
+ include ShopifyCli::MethodObject
8
+
9
+ property! :ctx
10
+ property! :type
11
+ property! :prompt,
12
+ converts: :to_proc,
13
+ default: -> { CLI::UI::Prompt.method(:ask) }
14
+
15
+ def call(project_details)
16
+ project_details.tap(&method(:prompt_for_registration))
17
+ end
18
+
19
+ private
20
+
21
+ def prompt_for_registration(project_details)
22
+ apps_and_registrations = load_registrations(type)
23
+ app, registration = choose_interactively(apps_and_registrations)
24
+ project_details.app = app
25
+ project_details.registration = registration
26
+ end
27
+
28
+ def choose_interactively(apps_and_registrations)
29
+ prompt.call(ctx.message("connect.ask_registration")) do |handler|
30
+ apps_and_registrations.each do |(app, extension)|
31
+ handler.option("#{app.title} by #{app.business_name}: #{extension.title}") { [app, extension] }
32
+ end
33
+ end
34
+ end
35
+
36
+ def load_registrations(type)
37
+ ctx.puts(@ctx.message("connect.loading_extensions"))
38
+ registrations = Tasks::GetExtensions.call(context: ctx, type: type)
39
+
40
+ registrations.empty? ? abort_no_registrations : registrations
41
+ end
42
+
43
+ def abort_no_registrations
44
+ ctx.puts(@ctx.message("connect.no_extensions", type))
45
+ ctx.puts(@ctx.message("connect.learn_about_extensions"))
46
+ raise ShopifyCli::AbortSilent
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -4,7 +4,21 @@ require "shopify_cli"
4
4
  module Extension
5
5
  module Messages
6
6
  MESSAGES = {
7
+ extension: {
8
+ help: <<~HELP,
9
+ Suite of commands for developing app extensions. See {{command:%1$s extension <command> --help}} for usage of each command.
10
+ Usage: {{command:%1$s extension [ %2$s ]}}
11
+ HELP
12
+ },
7
13
  create: {
14
+ help: <<~HELP,
15
+ Create a new app extension.
16
+ Usage: {{command:%s extension create <name>}}
17
+ Options:
18
+ {{command:--type=TYPE}} The type of extension you would like to create.
19
+ {{command:--name=NAME}} The name of your extension (50 characters).
20
+ {{command:--api-key=KEY}} The API key of your app.
21
+ HELP
8
22
  ask_name: "Extension name",
9
23
  invalid_name: "Extension name must be under %s characters",
10
24
  ask_type: "What type of extension are you creating?",
@@ -13,13 +27,13 @@ module Extension
13
27
  ready_to_start: <<~MESSAGE,
14
28
  {{v}} A new folder was generated at {{green:./%s}}.
15
29
  {{*}} You’re ready to start building {{green:%s}}!
16
- Navigate to the new folder, then run {{command:shopify serve}} to start a local server.
30
+ Navigate to the new folder, then run {{command:shopify extension serve}} to start a local server.
17
31
  MESSAGE
18
32
  learn_more: <<~MESSAGE,
19
33
  {{*}} Once you're ready to version and publish your extension,
20
- run {{command:shopify register}} to register this extension with one of your apps.
34
+ run {{command:shopify extension register}} to register this extension with one of your apps.
21
35
  MESSAGE
22
- try_again: "{{*}} Fix the errors and run {{command:shopify create extension}} again.",
36
+ try_again: "{{*}} Fix the errors and run {{command:shopify extension create}} again.",
23
37
  errors: {
24
38
  directory_exists: "Directory ‘%s’ already exists. Please remove it or choose a new name for your project.",
25
39
  },
@@ -28,34 +42,69 @@ module Extension
28
42
  ask_app: "Which app would you like to register this extension with?",
29
43
  no_apps: "{{x}} You don’t have any apps.",
30
44
  learn_about_apps: "{{*}} Learn more about building apps at <https://shopify.dev/concepts/apps>, " \
31
- "or try creating a new app using {{command:shopify create}}.",
32
- loading_apps: "Loading your apps...",
45
+ "or try creating a new app using {{command:shopify [node|rails] create}}.",
46
+ loading_apps: "Loading your apps",
33
47
  no_available_extensions: "{{x}} There are no available extensions for this app.",
34
48
  },
49
+ connect: {
50
+ connected: "Project now connected to {{green:%s: %s}}",
51
+ incomplete_configuration: "Cannot connect extension due to missing configuration information",
52
+ invalid_api_key: "The API key %s does not match any of your apps.",
53
+ ask_registration: "Which extension would you like to connect to?",
54
+ loading_extensions: "Loading your extensions…",
55
+ no_extensions: "{{x}} You don't have any extensions of type %s",
56
+ learn_about_extensions: "{{*}} Learn more about building extensions at <https://shopify.dev/concepts/apps>, " \
57
+ "or try creating a new extension using {{command:shopify extension create}}.",
58
+ help: <<~HELP,
59
+ {{command:%s extension connect}}: Connects an existing extension to Shopify CLI. Creates a config file.
60
+ Usage: {{command:%s extension connect}}
61
+ HELP
62
+ },
35
63
  build: {
36
- frame_title: "Building extension with: %s...",
64
+ help: <<~HELP,
65
+ Build your extension to prepare for deployment.
66
+ Usage: {{command:%s extension build}}
67
+ HELP
68
+ frame_title: "Building extension with: %s…",
37
69
  build_failure_message: "Failed to build extension code.",
38
70
  },
39
71
  register: {
72
+ help: <<~HELP,
73
+ Register your local extension to a Shopify app
74
+ Usage: {{command:%s extension register}}
75
+ Options:
76
+ {{command:--api-key=API_KEY}} The API key used to register an app with the extension. This can be found on the app page on Partners Dashboard.
77
+ HELP
40
78
  frame_title: "Registering Extension",
41
- waiting_text: "Registering with Shopify...",
79
+ waiting_text: "Registering with Shopify",
42
80
  already_registered: "Extension is already registered.",
43
81
  confirm_info: "This will create a new extension registration for %s, which can’t be undone.",
44
82
  confirm_question: "Would you like to register this extension? (y/n)",
45
83
  confirm_abort: "Extension was not registered.",
46
84
  success: "{{v}} Registered {{green:%s}}.",
47
- success_info: "{{*}} Run {{command:shopify push}} to push your extension to Shopify.",
85
+ success_info: "{{*}} Run {{command:shopify extension push}} to push your extension to Shopify.",
48
86
  },
49
87
  push: {
88
+ help: <<~HELP,
89
+ Push the current extension to Shopify.
90
+ Usage: {{command:%s extension push}}
91
+ HELP
50
92
  frame_title: "Pushing your extension to Shopify",
51
- waiting_text: "Pushing code to Shopify...",
93
+ waiting_text: "Pushing code to Shopify",
52
94
  pushed_with_errors: "{{x}} Code pushed to Shopify with errors on %s.",
53
- push_with_errors_info: "{{*}} Fix these errors and run {{command:shopify push}} to revalidate your extension.",
95
+ push_with_errors_info: "{{*}} Fix these errors and run {{command:shopify extension push}} to " \
96
+ "revalidate your extension.",
54
97
  success_confirmation: "{{v}} Pushed {{green:%s}} to a draft on %s.",
55
98
  success_info: "{{*}} Visit %s to version and publish your extension.",
56
99
  },
57
100
  serve: {
58
- frame_title: "Serving extension...",
101
+ help: <<~HELP,
102
+ Serve your extension in a local simulator for development.
103
+ Usage: {{command:%s extension serve}}
104
+ Options:
105
+ {{command:--tunnel=TUNNEL}} Establish an ngrok tunnel (default: false)
106
+ HELP
107
+ frame_title: "Serving extension…",
59
108
  no_available_ports_found: "No available ports found to run extension.",
60
109
  serve_failure_message: "Failed to run extension code.",
61
110
  serve_missing_information: "Missing shop or api_key.",
@@ -69,27 +118,31 @@ module Extension
69
118
  tunnel_running_at: "Tunnel running at: {{underline:%s}}",
70
119
  help: <<~HELP,
71
120
  Start or stop an http tunnel to your local development extension using ngrok.
72
- Usage: {{command:%s tunnel [ auth | start | stop | status ]}}
121
+ Usage: {{command:%s extension tunnel [ auth | start | stop | status ]}}
73
122
  HELP
74
123
  extended_help: <<~HELP,
75
124
  {{bold:Subcommands:}}
76
125
 
77
126
  {{cyan:auth}}: Writes an ngrok auth token to ~/.ngrok2/ngrok.yml to connect with an ngrok account.
78
127
  Visit https://dashboard.ngrok.com/signup to sign up.
79
- Usage: {{command:%1$s tunnel auth <token>}}
128
+ Usage: {{command:%1$s extension tunnel auth <token>}}
80
129
 
81
130
  {{cyan:start}}: Starts an ngrok tunnel, will print the URL for an existing tunnel if already running.
82
- Usage: {{command:%1$s tunnel start}}
131
+ Usage: {{command:%1$s extension tunnel start}}
83
132
  Options:
84
133
  {{command:--port=PORT}} Forward the ngrok subdomain to local port PORT. Defaults to %2$s.
85
134
 
86
135
  {{cyan:stop}}: Stops the ngrok tunnel.
87
- Usage: {{command:%1$s tunnel stop}}
136
+ Usage: {{command:%1$s extension tunnel stop}}
88
137
 
89
138
  {{cyan:status}}: Output the current status of the ngrok tunnel.
90
- Usage: {{command:%1$s tunnel status}}
139
+ Usage: {{command:%1$s extension tunnel status}}
91
140
  HELP
92
141
  },
142
+ check: {
143
+ help: "Check your extension for errors, suggestions, and best practices.",
144
+ unsupported: "{{red:%s projects are not supported for `extension check`}}",
145
+ },
93
146
  features: {
94
147
  argo: {
95
148
  missing_file_error: "Could not find built extension file.",
@@ -134,6 +187,21 @@ module Extension
134
187
  checkout_post_purchase: {
135
188
  name: "Checkout Post Purchase",
136
189
  },
190
+ theme_app_extension: {
191
+ name: "Theme App Extension",
192
+ tagline: "(limit 1 per app)",
193
+ overrides: {
194
+ register: {
195
+ confirm_info: "You can only create one %s extension per app, which can’t be undone.",
196
+ },
197
+ create: {
198
+ ready_to_start: <<~MESSAGE,
199
+ {{v}} A new folder was generated at {{green:./%s}}.
200
+ {{*}} You’re ready to start building {{green:%s}}!
201
+ MESSAGE
202
+ },
203
+ },
204
+ },
137
205
  }
138
206
  end
139
207
  end