shopify-cli 1.13.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+ require "theme_check"
3
+
4
+ module Extension
5
+ class Command
6
+ class Check < ExtensionCommand
7
+ class CheckOptions < ShopifyCli::Options
8
+ def initialize(ctx, theme_check)
9
+ super()
10
+ @theme_check = theme_check
11
+ @ctx = ctx
12
+ end
13
+
14
+ def parse(_options_block, args)
15
+ # Check if .theme-check.yml exists, or if another -C has been passed on the command line
16
+ unless args.include?("-C") || @ctx.file_exist?(".theme-check.yml")
17
+ args += ["-C", ":theme_app_extension"]
18
+ end
19
+ @theme_check.parse(args)
20
+ end
21
+ end
22
+
23
+ def initialize(*)
24
+ super
25
+ if project.specification_identifier == "THEME_APP_EXTENSION"
26
+ @theme_check = ThemeCheck::Cli.new
27
+ self.options = CheckOptions.new(@ctx, @theme_check)
28
+ end
29
+ end
30
+
31
+ def call(*)
32
+ if project.specification_identifier == "THEME_APP_EXTENSION"
33
+ @theme_check.run
34
+ else
35
+ @ctx.abort(@ctx.message("check.unsupported", project.specification_identifier))
36
+ end
37
+ end
38
+
39
+ def self.help
40
+ ShopifyCli::Context.message("check.help", ShopifyCli::TOOL_NAME)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+ module Extension
3
+ class Command
4
+ class Connect < ExtensionCommand
5
+ prerequisite_task :ensure_authenticated
6
+
7
+ def call(args, _)
8
+ with_connect_form(args) do |form|
9
+ ExtensionProject.write_env_file(
10
+ context: @ctx,
11
+ api_key: form.app.api_key,
12
+ api_secret: form.app.secret,
13
+ registration_id: form.registration.id,
14
+ registration_uuid: form.registration.uuid,
15
+ title: form.registration.title
16
+ )
17
+ @ctx.done(@ctx.message("connect.connected", form.app.title, form.registration.title))
18
+ end
19
+ end
20
+
21
+ def self.help
22
+ ShopifyCli::Context.new.message("connect.help", ShopifyCli::TOOL_NAME, ShopifyCli::TOOL_NAME)
23
+ end
24
+
25
+ private
26
+
27
+ def with_connect_form(args)
28
+ form = Forms::Connect.ask(@ctx, args, { type: specification_handler.identifier.downcase })
29
+ return @ctx.puts(self.class.help) if form.nil?
30
+
31
+ yield form
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,21 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Extension
4
- module Commands
4
+ class Command
5
5
  class Create < ShopifyCli::SubCommand
6
+ prerequisite_task :ensure_authenticated
7
+
6
8
  options do |parser, flags|
7
9
  parser.on("--name=NAME") { |name| flags[:name] = name }
8
10
  parser.on("--type=TYPE") { |type| flags[:type] = type.upcase }
9
11
  parser.on("--api-key=KEY") { |key| flags[:api_key] = key.downcase }
12
+ parser.on("--getting-started") { flags[:getting_started] = true }
10
13
  end
11
14
 
12
15
  def call(args, _)
13
- with_create_form(args) do |form|
16
+ with_create_form(args) do |form, message_for_extension|
14
17
  if Dir.exist?(form.directory_name)
15
- @ctx.abort(@ctx.message("create.errors.directory_exists", form.directory_name))
18
+ @ctx.abort(message_for_extension["create.errors.directory_exists", form.directory_name])
16
19
  end
17
20
 
18
- if form.type.create(form.directory_name, @ctx)
21
+ if form.type.create(form.directory_name, @ctx, getting_started: options.flags[:getting_started])
19
22
  ExtensionProject.write_cli_file(context: @ctx, type: form.type.identifier)
20
23
  ExtensionProject.write_env_file(
21
24
  context: @ctx,
@@ -24,23 +27,16 @@ module Extension
24
27
  api_secret: form.app.secret
25
28
  )
26
29
 
27
- @ctx.puts(@ctx.message("create.ready_to_start", form.directory_name, form.name))
28
- @ctx.puts(@ctx.message("create.learn_more", form.type.name))
30
+ @ctx.puts(message_for_extension["create.ready_to_start", form.directory_name, form.name])
31
+ @ctx.puts(message_for_extension["create.learn_more", form.type.name])
29
32
  else
30
- @ctx.puts(@ctx.message("create.try_again"))
33
+ @ctx.puts(message_for_extension["create.try_again"])
31
34
  end
32
35
  end
33
36
  end
34
37
 
35
38
  def self.help
36
- <<~HELP
37
- Create a new app extension.
38
- Usage: {{command:#{ShopifyCli::TOOL_NAME} create extension}}
39
- Options:
40
- {{command:--type=TYPE}} The type of extension you would like to create.
41
- {{command:--name=NAME}} The name of your extension (50 characters).
42
- {{command:--api-key=KEY}} The API key of your app.
43
- HELP
39
+ @ctx.message("create.help", ShopifyCli::TOOL_NAME)
44
40
  end
45
41
 
46
42
  private
@@ -49,7 +45,7 @@ module Extension
49
45
  form = Forms::Create.ask(@ctx, args, options.flags)
50
46
  return @ctx.puts(self.class.help) if form.nil?
51
47
 
52
- yield form
48
+ yield form, form.type.method(:message_for_extension)
53
49
  end
54
50
  end
55
51
  end
@@ -2,8 +2,8 @@
2
2
  require "shopify_cli"
3
3
 
4
4
  module Extension
5
- module Commands
6
- class ExtensionCommand < ShopifyCli::Command
5
+ class Command
6
+ class ExtensionCommand < ShopifyCli::SubCommand
7
7
  def project
8
8
  @project ||= ExtensionProject.current
9
9
  end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+ require "shopify_cli"
3
+
4
+ module Extension
5
+ class Command
6
+ class Info < ExtensionCommand
7
+ hidden_feature
8
+
9
+ def call(*)
10
+ @ctx.puts("Extension Title: #{project.title}")
11
+ @ctx.puts("Extension UUID: #{project.registration_uuid}")
12
+ @ctx.puts("Extension ID: #{project.registration_id}")
13
+ theme_app_extension_additional_info
14
+ end
15
+
16
+ def self.help
17
+ ShopifyCli::Context.new.message("info.help", ShopifyCli::TOOL_NAME)
18
+ end
19
+
20
+ private
21
+
22
+ OPENING_SCHEMA = "{%schema%}"
23
+ CLOSING_SCHEMA = "{%endschema%}"
24
+
25
+ def theme_app_extension_additional_info
26
+ if project.specification_identifier == "THEME_APP_EXTENSION" && (infos = block_infos)
27
+ title = to_handle(app.title)
28
+ uuid = project.registration_uuid
29
+ @ctx.puts("Block Infos \n")
30
+ index = 1
31
+ infos.each do |type, blocks_name|
32
+ @ctx.puts(" << #{type} >>\n")
33
+ blocks_name.each do |block_name|
34
+ @ctx.puts(" #{index}. shopify://apps/#{title}/blocks/#{block_name}/#{uuid} \n")
35
+ index += 1
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ def app
42
+ @app ||= Tasks::GetApp.call(context: @ctx, api_key: project.app.api_key)
43
+ end
44
+
45
+ def block_infos
46
+ block_infos = {}
47
+ Dir["blocks/*.liquid"].map do |filename|
48
+ block_name = File.basename(filename, ".liquid")
49
+ json_schema = block_info(filename)
50
+
51
+ next unless json_schema
52
+ block_type = json_schema["target"] == "section" ? "App Block" : "App Embed"
53
+ block_infos[block_type] ||= []
54
+ block_infos[block_type] << block_name
55
+ end
56
+ block_infos
57
+ end
58
+
59
+ def block_info(filename)
60
+ output = File.read(filename)
61
+ output = output.gsub(/\s+/, "")
62
+
63
+ if output
64
+ opening_index = output.index(OPENING_SCHEMA) + OPENING_SCHEMA.size
65
+ closing_index = output.index(CLOSING_SCHEMA) - 1
66
+
67
+ if (schema = output.slice(opening_index..closing_index))
68
+ json_schema = JSON.parse(schema)
69
+ end
70
+ end
71
+ json_schema
72
+ rescue JSON::ParserError
73
+ {}
74
+ end
75
+
76
+ def to_handle(s)
77
+ s = s.dup
78
+ s.downcase!
79
+ s.delete!("'\"()[]")
80
+ s.gsub!(/\W+/, "-")
81
+ s.gsub!(/\A-+|-+\z/, "")
82
+ -s
83
+ end
84
+ end
85
+ end
86
+ end
@@ -2,13 +2,15 @@
2
2
  require "shopify_cli"
3
3
 
4
4
  module Extension
5
- module Commands
5
+ class Command
6
6
  class Push < ExtensionCommand
7
+ prerequisite_task ensure_project_type: :extension
8
+
7
9
  TIME_DISPLAY_FORMAT = "%B %d, %Y %H:%M:%S %Z"
8
10
 
9
11
  def call(args, name)
10
- Commands::Register.new(@ctx).call(args, name) unless project.registered?
11
- Commands::Build.new(@ctx).call(args, name)
12
+ Command::Register.new(@ctx).call(args, name) unless project.registered?
13
+ Command::Build.new(@ctx).call(args, name) unless specification_handler.specification.options[:skip_build]
12
14
 
13
15
  CLI::UI::Frame.open(@ctx.message("push.frame_title")) do
14
16
  updated_draft_version = update_draft
@@ -17,10 +19,7 @@ module Extension
17
19
  end
18
20
 
19
21
  def self.help
20
- <<~HELP
21
- Push the current extension to Shopify.
22
- Usage: {{command:#{ShopifyCli::TOOL_NAME} push}}
23
- HELP
22
+ ShopifyCli::Context.new.message("push.help", ShopifyCli::TOOL_NAME)
24
23
  end
25
24
 
26
25
  private
@@ -63,6 +62,8 @@ module Extension
63
62
  extension_context: specification_handler.extension_context(@ctx)
64
63
  )
65
64
  end
65
+ rescue Extension::Errors::ExtensionError => e
66
+ @ctx.abort(e)
66
67
  end
67
68
  end
68
69
  end
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Extension
4
- module Commands
4
+ class Command
5
5
  class Register < ExtensionCommand
6
+ prerequisite_task ensure_project_type: :extension
7
+
6
8
  def call(_args, _command_name)
7
9
  CLI::UI::Frame.open(@ctx.message("register.frame_title")) do
8
10
  @ctx.abort(@ctx.message("register.already_registered")) if project.registered?
@@ -18,10 +20,7 @@ module Extension
18
20
  end
19
21
 
20
22
  def self.help
21
- <<~HELP
22
- Register your local extension to a Shopify app
23
- Usage: {{command:#{ShopifyCli::TOOL_NAME} register}}
24
- HELP
23
+ ShopifyCli::Context.new.message("register.help", ShopifyCli::TOOL_NAME)
25
24
  end
26
25
 
27
26
  private
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Extension
4
- module Commands
4
+ class Command
5
5
  class Serve < ExtensionCommand
6
+ prerequisite_task ensure_project_type: :extension
7
+
6
8
  DEFAULT_PORT = 39351
7
9
 
8
10
  options do |parser, flags|
@@ -12,7 +14,7 @@ module Extension
12
14
  class RuntimeConfiguration
13
15
  include SmartProperties
14
16
 
15
- property! :tunnel_url, accepts: String, default: ""
17
+ property :tunnel_url, accepts: String, default: nil
16
18
  property! :tunnel_requested, accepts: [true, false], reader: :tunnel_requested?, default: true
17
19
  property! :port, accepts: (1...(2**16)), default: DEFAULT_PORT
18
20
  end
@@ -31,12 +33,7 @@ module Extension
31
33
  end
32
34
 
33
35
  def self.help
34
- <<~HELP
35
- Serve your extension in a local simulator for development.
36
- Usage: {{command:#{ShopifyCli::TOOL_NAME} serve}}
37
- Options:
38
- {{command:--tunnel=TUNNEL}} Establish an ngrok tunnel (default: false)
39
- HELP
36
+ ShopifyCli::Context.new.message("serve.help", ShopifyCli::TOOL_NAME)
40
37
  end
41
38
 
42
39
  private
@@ -2,8 +2,10 @@
2
2
  require "shopify_cli"
3
3
 
4
4
  module Extension
5
- module Commands
5
+ class Command
6
6
  class Tunnel < ExtensionCommand
7
+ prerequisite_task ensure_project_type: :extension
8
+
7
9
  options do |parser, flags|
8
10
  parser.on("--port=PORT") { |port| flags[:port] = port }
9
11
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Errors
5
+ class ExtensionError < StandardError; end
6
+ class InvalidFilenameError < ExtensionError; end
7
+ class BundleTooLargeError < ExtensionError; end
8
+ end
9
+ end
@@ -15,7 +15,13 @@ module Extension
15
15
  end
16
16
 
17
17
  def write_env_file(
18
- context:, title:, api_key: "", api_secret: "", registration_id: nil, registration_uuid: nil
18
+ context:,
19
+ title:,
20
+ api_key: "",
21
+ api_secret: "",
22
+ registration_id: nil,
23
+ registration_uuid: nil,
24
+ resource_url: nil
19
25
  )
20
26
  ShopifyCli::Resources::EnvFile.new(
21
27
  api_key: api_key,
@@ -24,6 +30,7 @@ module Extension
24
30
  ExtensionProjectKeys::TITLE_KEY => title,
25
31
  ExtensionProjectKeys::REGISTRATION_ID_KEY => registration_id,
26
32
  ExtensionProjectKeys::REGISTRATION_UUID_KEY => registration_uuid || generate_temporary_uuid,
33
+ ExtensionProjectKeys::RESOURCE_URL_KEY => resource_url,
27
34
  }.compact
28
35
  ).write(context)
29
36
 
@@ -42,6 +49,7 @@ module Extension
42
49
  end
43
50
 
44
51
  def app
52
+ validate_env_present
45
53
  Models::App.new(api_key: env["api_key"], secret: env["secret"])
46
54
  end
47
55
 
@@ -71,6 +79,10 @@ module Extension
71
79
  get_extra_field(ExtensionProjectKeys::REGISTRATION_UUID_KEY)
72
80
  end
73
81
 
82
+ def resource_url
83
+ get_extra_field(ExtensionProjectKeys::RESOURCE_URL_KEY)
84
+ end
85
+
74
86
  def reload
75
87
  @env = nil
76
88
  end
@@ -82,6 +94,11 @@ module Extension
82
94
  private
83
95
 
84
96
  def get_extra_field(key)
97
+ unless env
98
+ Kernel.puts("Run the command inside the correct extension directory.")
99
+ exit
100
+ end
101
+
85
102
  extra = env[:extra] || {}
86
103
  extra[key]
87
104
  end
@@ -91,9 +108,15 @@ module Extension
91
108
  end
92
109
 
93
110
  def property_present?(key)
111
+ validate_env_present
94
112
  !env[key].nil? && !env[key].strip.empty?
95
113
  end
96
114
 
115
+ def validate_env_present
116
+ return if env
117
+ raise ShopifyCli::Abort, "Missing .env file. Run `shopify extension connect` to generate an .env file."
118
+ end
119
+
97
120
  def integer?(value)
98
121
  value.to_i.to_s == value.to_s
99
122
  end
@@ -7,5 +7,6 @@ module Extension
7
7
  REGISTRATION_UUID_KEY = "EXTENSION_UUID"
8
8
  SPECIFICATION_IDENTIFIER_KEY = "EXTENSION_TYPE"
9
9
  TITLE_KEY = "EXTENSION_TITLE"
10
+ RESOURCE_URL_KEY = "EXTENSION_RESOURCE_URL"
10
11
  end
11
12
  end