shopify-cli 0.9.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 (273) hide show
  1. checksums.yaml +7 -0
  2. data/.github/CODEOWNERS +1 -0
  3. data/.github/CODE_OF_CONDUCT.md +73 -0
  4. data/.github/CONTRIBUTING.md +51 -0
  5. data/.github/DESIGN.md +153 -0
  6. data/.github/ISSUE_TEMPLATE.md +38 -0
  7. data/.github/PULL_REQUEST_TEMPLATE.md +22 -0
  8. data/.github/probots.yml +3 -0
  9. data/.gitignore +19 -0
  10. data/.rubocop.yml +47 -0
  11. data/.ruby-version +1 -0
  12. data/.travis.yml +12 -0
  13. data/Gemfile +22 -0
  14. data/Gemfile.lock +77 -0
  15. data/LICENSE.md +7 -0
  16. data/README.md +13 -0
  17. data/Rakefile +101 -0
  18. data/SECURITY.md +59 -0
  19. data/Vagrantfile +17 -0
  20. data/bin/load_shopify.rb +20 -0
  21. data/bin/shopify +32 -0
  22. data/dev.yml +17 -0
  23. data/docs/Gemfile +5 -0
  24. data/docs/Gemfile.lock +248 -0
  25. data/docs/_config.yml +16 -0
  26. data/docs/_data/nav.yml +26 -0
  27. data/docs/_includes/footer.html +15 -0
  28. data/docs/_includes/head.html +19 -0
  29. data/docs/_includes/sidebar_nav.html +22 -0
  30. data/docs/_includes/toc.html +112 -0
  31. data/docs/_layouts/default.html +79 -0
  32. data/docs/app/node/commands/index.md +82 -0
  33. data/docs/app/node/index.md +35 -0
  34. data/docs/app/rails/commands/index.md +80 -0
  35. data/docs/app/rails/index.md +36 -0
  36. data/docs/core/index.md +70 -0
  37. data/docs/css/docs.css +157 -0
  38. data/docs/getting-started/index.md +61 -0
  39. data/docs/help/start-app/index.md +6 -0
  40. data/docs/images/header.png +0 -0
  41. data/docs/index.md +27 -0
  42. data/docs/installing-ruby.md +28 -0
  43. data/ext/shopify-cli/extconf.rb +27 -0
  44. data/install.sh +7 -0
  45. data/lib/docgen/class_template.md.erb +81 -0
  46. data/lib/docgen/index_template.md.erb +5 -0
  47. data/lib/docgen/markdown.rb +101 -0
  48. data/lib/graphql/admin_introspection.graphql +87 -0
  49. data/lib/graphql/all_organizations.graphql +19 -0
  50. data/lib/graphql/all_orgs_with_apps.graphql +30 -0
  51. data/lib/graphql/api_versions.graphql +6 -0
  52. data/lib/graphql/convert_dev_to_test_store.graphql +10 -0
  53. data/lib/graphql/create_app.graphql +20 -0
  54. data/lib/graphql/create_customer.graphql +9 -0
  55. data/lib/graphql/create_draft_order.graphql +8 -0
  56. data/lib/graphql/create_product.graphql +9 -0
  57. data/lib/graphql/extension_create.graphql +21 -0
  58. data/lib/graphql/extension_update_draft.graphql +18 -0
  59. data/lib/graphql/find_organization.graphql +17 -0
  60. data/lib/graphql/get_app_urls.graphql +6 -0
  61. data/lib/graphql/update_dashboard_urls.graphql +8 -0
  62. data/lib/project_types/extension/cli.rb +71 -0
  63. data/lib/project_types/extension/commands/build.rb +29 -0
  64. data/lib/project_types/extension/commands/create.rb +49 -0
  65. data/lib/project_types/extension/commands/extension_command.rb +22 -0
  66. data/lib/project_types/extension/commands/push.rb +69 -0
  67. data/lib/project_types/extension/commands/register.rb +78 -0
  68. data/lib/project_types/extension/commands/serve.rb +24 -0
  69. data/lib/project_types/extension/commands/tunnel.rb +69 -0
  70. data/lib/project_types/extension/extension_project.rb +85 -0
  71. data/lib/project_types/extension/extension_project_keys.rb +10 -0
  72. data/lib/project_types/extension/features/argo.rb +48 -0
  73. data/lib/project_types/extension/features/argo_dependencies.rb +28 -0
  74. data/lib/project_types/extension/features/argo_setup.rb +54 -0
  75. data/lib/project_types/extension/features/argo_setup_step.rb +31 -0
  76. data/lib/project_types/extension/features/argo_setup_steps.rb +53 -0
  77. data/lib/project_types/extension/features/tunnel_url.rb +20 -0
  78. data/lib/project_types/extension/forms/create.rb +52 -0
  79. data/lib/project_types/extension/forms/register.rb +48 -0
  80. data/lib/project_types/extension/messages/message_loading.rb +37 -0
  81. data/lib/project_types/extension/messages/messages.rb +126 -0
  82. data/lib/project_types/extension/models/app.rb +14 -0
  83. data/lib/project_types/extension/models/registration.rb +19 -0
  84. data/lib/project_types/extension/models/type.rb +76 -0
  85. data/lib/project_types/extension/models/types/checkout_post_purchase.rb +20 -0
  86. data/lib/project_types/extension/models/types/subscription_management.rb +20 -0
  87. data/lib/project_types/extension/models/validation_error.rb +17 -0
  88. data/lib/project_types/extension/models/version.rb +15 -0
  89. data/lib/project_types/extension/tasks/converters/registration_converter.rb +26 -0
  90. data/lib/project_types/extension/tasks/converters/validation_error_converter.rb +25 -0
  91. data/lib/project_types/extension/tasks/converters/version_converter.rb +28 -0
  92. data/lib/project_types/extension/tasks/create_extension.rb +31 -0
  93. data/lib/project_types/extension/tasks/get_apps.rb +34 -0
  94. data/lib/project_types/extension/tasks/update_draft.rb +29 -0
  95. data/lib/project_types/extension/tasks/user_errors.rb +45 -0
  96. data/lib/project_types/node/cli.rb +37 -0
  97. data/lib/project_types/node/commands/create.rb +117 -0
  98. data/lib/project_types/node/commands/deploy.rb +22 -0
  99. data/lib/project_types/node/commands/deploy/heroku.rb +91 -0
  100. data/lib/project_types/node/commands/generate.rb +51 -0
  101. data/lib/project_types/node/commands/generate/billing.rb +37 -0
  102. data/lib/project_types/node/commands/generate/page.rb +55 -0
  103. data/lib/project_types/node/commands/generate/webhook.rb +33 -0
  104. data/lib/project_types/node/commands/open.rb +16 -0
  105. data/lib/project_types/node/commands/populate.rb +23 -0
  106. data/lib/project_types/node/commands/populate/customer.rb +31 -0
  107. data/lib/project_types/node/commands/populate/draft_order.rb +28 -0
  108. data/lib/project_types/node/commands/populate/product.rb +30 -0
  109. data/lib/project_types/node/commands/serve.rb +45 -0
  110. data/lib/project_types/node/commands/tunnel.rb +39 -0
  111. data/lib/project_types/node/forms/create.rb +87 -0
  112. data/lib/project_types/node/messages/messages.rb +260 -0
  113. data/lib/project_types/rails/cli.rb +41 -0
  114. data/lib/project_types/rails/commands/create.rb +126 -0
  115. data/lib/project_types/rails/commands/deploy.rb +22 -0
  116. data/lib/project_types/rails/commands/deploy/heroku.rb +113 -0
  117. data/lib/project_types/rails/commands/generate.rb +49 -0
  118. data/lib/project_types/rails/commands/generate/webhook.rb +39 -0
  119. data/lib/project_types/rails/commands/open.rb +16 -0
  120. data/lib/project_types/rails/commands/populate.rb +23 -0
  121. data/lib/project_types/rails/commands/populate/customer.rb +31 -0
  122. data/lib/project_types/rails/commands/populate/draft_order.rb +28 -0
  123. data/lib/project_types/rails/commands/populate/product.rb +30 -0
  124. data/lib/project_types/rails/commands/serve.rb +47 -0
  125. data/lib/project_types/rails/commands/tunnel.rb +39 -0
  126. data/lib/project_types/rails/forms/create.rb +116 -0
  127. data/lib/project_types/rails/gem.rb +56 -0
  128. data/lib/project_types/rails/messages/messages.rb +283 -0
  129. data/lib/project_types/rails/ruby.rb +17 -0
  130. data/lib/project_types/script/cli.rb +76 -0
  131. data/lib/project_types/script/commands/create.rb +45 -0
  132. data/lib/project_types/script/commands/disable.rb +36 -0
  133. data/lib/project_types/script/commands/enable.rb +46 -0
  134. data/lib/project_types/script/commands/push.rb +39 -0
  135. data/lib/project_types/script/config/extension_points.yml +18 -0
  136. data/lib/project_types/script/errors.rb +16 -0
  137. data/lib/project_types/script/forms/create.rb +29 -0
  138. data/lib/project_types/script/forms/enable.rb +24 -0
  139. data/lib/project_types/script/forms/push.rb +19 -0
  140. data/lib/project_types/script/forms/script_form.rb +66 -0
  141. data/lib/project_types/script/graphql/app_script_update_or_create.graphql +27 -0
  142. data/lib/project_types/script/graphql/script_service_proxy.graphql +8 -0
  143. data/lib/project_types/script/graphql/shop_script_delete.graphql +14 -0
  144. data/lib/project_types/script/graphql/shop_script_update_or_create.graphql +28 -0
  145. data/lib/project_types/script/layers/application/build_script.rb +43 -0
  146. data/lib/project_types/script/layers/application/create_script.rb +47 -0
  147. data/lib/project_types/script/layers/application/disable_script.rb +19 -0
  148. data/lib/project_types/script/layers/application/enable_script.rb +21 -0
  149. data/lib/project_types/script/layers/application/extension_points.rb +17 -0
  150. data/lib/project_types/script/layers/application/project_dependencies.rb +34 -0
  151. data/lib/project_types/script/layers/application/push_script.rb +30 -0
  152. data/lib/project_types/script/layers/domain/errors.rb +25 -0
  153. data/lib/project_types/script/layers/domain/extension_point.rb +29 -0
  154. data/lib/project_types/script/layers/domain/push_package.rb +29 -0
  155. data/lib/project_types/script/layers/domain/script.rb +18 -0
  156. data/lib/project_types/script/layers/infrastructure/assemblyscript_dependency_manager.rb +73 -0
  157. data/lib/project_types/script/layers/infrastructure/assemblyscript_tsconfig.rb +38 -0
  158. data/lib/project_types/script/layers/infrastructure/assemblyscript_wasm_builder.rb +39 -0
  159. data/lib/project_types/script/layers/infrastructure/dependency_manager.rb +36 -0
  160. data/lib/project_types/script/layers/infrastructure/errors.rb +38 -0
  161. data/lib/project_types/script/layers/infrastructure/extension_point_repository.rb +31 -0
  162. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +47 -0
  163. data/lib/project_types/script/layers/infrastructure/script_builder.rb +34 -0
  164. data/lib/project_types/script/layers/infrastructure/script_repository.rb +89 -0
  165. data/lib/project_types/script/layers/infrastructure/script_service.rb +165 -0
  166. data/lib/project_types/script/layers/infrastructure/test_suite_repository.rb +59 -0
  167. data/lib/project_types/script/messages/messages.rb +204 -0
  168. data/lib/project_types/script/script_project.rb +37 -0
  169. data/lib/project_types/script/templates/ts/as-pect.config.js +21 -0
  170. data/lib/project_types/script/ui/error_handler.rb +136 -0
  171. data/lib/project_types/script/ui/strict_spinner.rb +22 -0
  172. data/lib/rubygems_plugin.rb +18 -0
  173. data/lib/shopify-cli/admin_api.rb +99 -0
  174. data/lib/shopify-cli/admin_api/populate_resource_command.rb +165 -0
  175. data/lib/shopify-cli/admin_api/schema.rb +32 -0
  176. data/lib/shopify-cli/api.rb +104 -0
  177. data/lib/shopify-cli/command.rb +67 -0
  178. data/lib/shopify-cli/commands.rb +28 -0
  179. data/lib/shopify-cli/commands/connect.rb +108 -0
  180. data/lib/shopify-cli/commands/create.rb +50 -0
  181. data/lib/shopify-cli/commands/help.rb +79 -0
  182. data/lib/shopify-cli/commands/logout.rb +23 -0
  183. data/lib/shopify-cli/commands/system.rb +135 -0
  184. data/lib/shopify-cli/commands/version.rb +15 -0
  185. data/lib/shopify-cli/context.rb +372 -0
  186. data/lib/shopify-cli/core.rb +9 -0
  187. data/lib/shopify-cli/core/entry_point.rb +40 -0
  188. data/lib/shopify-cli/core/executor.rb +21 -0
  189. data/lib/shopify-cli/core/help_resolver.rb +20 -0
  190. data/lib/shopify-cli/core/monorail.rb +118 -0
  191. data/lib/shopify-cli/db.rb +114 -0
  192. data/lib/shopify-cli/form.rb +40 -0
  193. data/lib/shopify-cli/git.rb +141 -0
  194. data/lib/shopify-cli/helpers.rb +5 -0
  195. data/lib/shopify-cli/helpers/haikunator.rb +92 -0
  196. data/lib/shopify-cli/heroku.rb +97 -0
  197. data/lib/shopify-cli/js_deps.rb +110 -0
  198. data/lib/shopify-cli/js_system.rb +98 -0
  199. data/lib/shopify-cli/messages/messages.rb +287 -0
  200. data/lib/shopify-cli/oauth.rb +192 -0
  201. data/lib/shopify-cli/oauth/servlet.rb +61 -0
  202. data/lib/shopify-cli/options.rb +40 -0
  203. data/lib/shopify-cli/packager.rb +116 -0
  204. data/lib/shopify-cli/partners_api.rb +114 -0
  205. data/lib/shopify-cli/partners_api/organizations.rb +32 -0
  206. data/lib/shopify-cli/process_supervision.rb +187 -0
  207. data/lib/shopify-cli/project.rb +191 -0
  208. data/lib/shopify-cli/project_type.rb +83 -0
  209. data/lib/shopify-cli/resources.rb +5 -0
  210. data/lib/shopify-cli/resources/env_file.rb +96 -0
  211. data/lib/shopify-cli/sub_command.rb +15 -0
  212. data/lib/shopify-cli/task.rb +10 -0
  213. data/lib/shopify-cli/tasks.rb +32 -0
  214. data/lib/shopify-cli/tasks/create_api_client.rb +29 -0
  215. data/lib/shopify-cli/tasks/ensure_dev_store.rb +41 -0
  216. data/lib/shopify-cli/tasks/ensure_env.rb +31 -0
  217. data/lib/shopify-cli/tasks/ensure_loopback_url.rb +20 -0
  218. data/lib/shopify-cli/tasks/update_dashboard_urls.rb +44 -0
  219. data/lib/shopify-cli/tunnel.rb +154 -0
  220. data/lib/shopify-cli/version.rb +3 -0
  221. data/lib/shopify_cli.rb +132 -0
  222. data/shopify-cli.gemspec +40 -0
  223. data/shopify.fish +12 -0
  224. data/shopify.sh +11 -0
  225. data/vendor/deps/cli-kit/REVISION +1 -0
  226. data/vendor/deps/cli-kit/lib/cli/kit.rb +60 -0
  227. data/vendor/deps/cli-kit/lib/cli/kit/autocall.rb +21 -0
  228. data/vendor/deps/cli-kit/lib/cli/kit/base_command.rb +49 -0
  229. data/vendor/deps/cli-kit/lib/cli/kit/command_registry.rb +94 -0
  230. data/vendor/deps/cli-kit/lib/cli/kit/config.rb +133 -0
  231. data/vendor/deps/cli-kit/lib/cli/kit/error_handler.rb +115 -0
  232. data/vendor/deps/cli-kit/lib/cli/kit/executor.rb +81 -0
  233. data/vendor/deps/cli-kit/lib/cli/kit/ini.rb +102 -0
  234. data/vendor/deps/cli-kit/lib/cli/kit/levenshtein.rb +82 -0
  235. data/vendor/deps/cli-kit/lib/cli/kit/logger.rb +76 -0
  236. data/vendor/deps/cli-kit/lib/cli/kit/resolver.rb +60 -0
  237. data/vendor/deps/cli-kit/lib/cli/kit/ruby_backports/enumerable.rb +6 -0
  238. data/vendor/deps/cli-kit/lib/cli/kit/support.rb +9 -0
  239. data/vendor/deps/cli-kit/lib/cli/kit/support/test_helper.rb +244 -0
  240. data/vendor/deps/cli-kit/lib/cli/kit/system.rb +207 -0
  241. data/vendor/deps/cli-kit/lib/cli/kit/util.rb +189 -0
  242. data/vendor/deps/cli-kit/lib/cli/kit/version.rb +5 -0
  243. data/vendor/deps/cli-ui/REVISION +1 -0
  244. data/vendor/deps/cli-ui/lib/cli/ui.rb +187 -0
  245. data/vendor/deps/cli-ui/lib/cli/ui/ansi.rb +153 -0
  246. data/vendor/deps/cli-ui/lib/cli/ui/box.rb +15 -0
  247. data/vendor/deps/cli-ui/lib/cli/ui/color.rb +79 -0
  248. data/vendor/deps/cli-ui/lib/cli/ui/formatter.rb +179 -0
  249. data/vendor/deps/cli-ui/lib/cli/ui/frame.rb +310 -0
  250. data/vendor/deps/cli-ui/lib/cli/ui/glyph.rb +78 -0
  251. data/vendor/deps/cli-ui/lib/cli/ui/progress.rb +88 -0
  252. data/vendor/deps/cli-ui/lib/cli/ui/prompt.rb +248 -0
  253. data/vendor/deps/cli-ui/lib/cli/ui/prompt/interactive_options.rb +472 -0
  254. data/vendor/deps/cli-ui/lib/cli/ui/prompt/options_handler.rb +24 -0
  255. data/vendor/deps/cli-ui/lib/cli/ui/spinner.rb +48 -0
  256. data/vendor/deps/cli-ui/lib/cli/ui/spinner/async.rb +40 -0
  257. data/vendor/deps/cli-ui/lib/cli/ui/spinner/spin_group.rb +241 -0
  258. data/vendor/deps/cli-ui/lib/cli/ui/stdout_router.rb +227 -0
  259. data/vendor/deps/cli-ui/lib/cli/ui/terminal.rb +36 -0
  260. data/vendor/deps/cli-ui/lib/cli/ui/truncater.rb +102 -0
  261. data/vendor/deps/cli-ui/lib/cli/ui/version.rb +5 -0
  262. data/vendor/deps/smart_properties/REVISION +1 -0
  263. data/vendor/deps/smart_properties/lib/smart_properties.rb +174 -0
  264. data/vendor/deps/smart_properties/lib/smart_properties/errors.rb +114 -0
  265. data/vendor/deps/smart_properties/lib/smart_properties/property.rb +162 -0
  266. data/vendor/deps/smart_properties/lib/smart_properties/property_collection.rb +83 -0
  267. data/vendor/deps/smart_properties/lib/smart_properties/validations.rb +8 -0
  268. data/vendor/deps/smart_properties/lib/smart_properties/validations/ancestor.rb +27 -0
  269. data/vendor/deps/smart_properties/lib/smart_properties/version.rb +3 -0
  270. data/vendor/lib/semantic/LICENSE +20 -0
  271. data/vendor/lib/semantic/semantic.rb +4 -0
  272. data/vendor/lib/semantic/version.rb +180 -0
  273. metadata +374 -0
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ require 'shopify_cli'
3
+
4
+ module Extension
5
+ module Commands
6
+ class Build < ExtensionCommand
7
+ hidden_command
8
+
9
+ YARN_BUILD_COMMAND = %w(build)
10
+ NPM_BUILD_COMMAND = %w(run-script build)
11
+
12
+ def call(_args, _command_name)
13
+ system = ShopifyCli::JsSystem.new(ctx: @ctx)
14
+
15
+ CLI::UI::Frame.open(@ctx.message('build.frame_title', system.package_manager)) do
16
+ success = system.call(yarn: YARN_BUILD_COMMAND, npm: NPM_BUILD_COMMAND)
17
+ @ctx.abort(@ctx.message('build.build_failure_message')) unless success
18
+ end
19
+ end
20
+
21
+ def self.help
22
+ <<~HELP
23
+ Build your extension to prepare for deployment.
24
+ Usage: {{command:#{ShopifyCli::TOOL_NAME} build}}
25
+ HELP
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Commands
5
+ class Create < ShopifyCli::SubCommand
6
+ options do |parser, flags|
7
+ parser.on('--name=NAME') { |name| flags[:name] = name }
8
+ parser.on('--type=TYPE') { |type| flags[:type] = type.upcase }
9
+ end
10
+
11
+ def call(args, _)
12
+ with_create_form(args) do |form|
13
+ if Dir.exist?(form.directory_name)
14
+ @ctx.abort(@ctx.message('create.errors.directory_exists', form.directory_name))
15
+ end
16
+
17
+ if form.type.create(form.directory_name, @ctx)
18
+ ExtensionProject.write_cli_file(context: @ctx, type: form.type.identifier)
19
+ ExtensionProject.write_env_file(context: @ctx, title: form.name)
20
+
21
+ @ctx.puts(@ctx.message('create.ready_to_start', form.directory_name, form.name))
22
+ @ctx.puts(@ctx.message('create.learn_more', form.type.name))
23
+ else
24
+ @ctx.puts(@ctx.message('create.try_again'))
25
+ end
26
+ end
27
+ end
28
+
29
+ def self.help
30
+ <<~HELP
31
+ Create a new app extension.
32
+ Usage: {{command:#{ShopifyCli::TOOL_NAME} create extension <name>}}
33
+ Options:
34
+ {{command:--type=TYPE}} The type of extension you would like to create.
35
+ {{command:--name=NAME}} The name of your extension (50 characters).”
36
+ HELP
37
+ end
38
+
39
+ private
40
+
41
+ def with_create_form(args)
42
+ form = Forms::Create.ask(@ctx, args, options.flags)
43
+ return @ctx.puts(self.class.help) if form.nil?
44
+
45
+ yield form
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+ require 'shopify_cli'
3
+
4
+ module Extension
5
+ module Commands
6
+ class ExtensionCommand < ShopifyCli::Command
7
+ def project
8
+ @project ||= ExtensionProject.current
9
+ end
10
+
11
+ def extension_type
12
+ @extension_type ||= begin
13
+ unless Models::Type.valid?(project.extension_type_identifier)
14
+ @ctx.abort(@ctx.message('errors.unknown_type', project.extension_type_identifier))
15
+ end
16
+
17
+ Models::Type.load_type(project.extension_type_identifier)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+ require 'shopify_cli'
3
+
4
+ module Extension
5
+ module Commands
6
+ class Push < ExtensionCommand
7
+ TIME_DISPLAY_FORMAT = "%B %d, %Y %H:%M:%S %Z"
8
+
9
+ def call(args, name)
10
+ Commands::Register.new(@ctx).call(args, name) unless project.registered?
11
+ Commands::Build.new(@ctx).call(args, name)
12
+
13
+ CLI::UI::Frame.open(@ctx.message('push.frame_title')) do
14
+ updated_draft_version = update_draft
15
+ show_message(updated_draft_version)
16
+ end
17
+ end
18
+
19
+ def self.help
20
+ <<~HELP
21
+ Push the current extension to Shopify.
22
+ Usage: {{command:#{ShopifyCli::TOOL_NAME} push}}
23
+ HELP
24
+ end
25
+
26
+ private
27
+
28
+ def show_message(draft)
29
+ draft.validation_errors.empty? ? output_success_messages(draft) : output_validation_errors(draft)
30
+ end
31
+
32
+ def output_success_messages(draft)
33
+ @ctx.puts(@ctx.message('push.success_confirmation', project.title, format_time(draft.last_user_interaction_at)))
34
+ @ctx.puts(@ctx.message('push.success_info', draft.location))
35
+ end
36
+
37
+ def output_validation_errors(draft)
38
+ @ctx.puts(@ctx.message('push.pushed_with_errors', format_time(draft.last_user_interaction_at)))
39
+
40
+ draft.validation_errors.each do |error|
41
+ @ctx.puts(format('{{x}} %s: %s', error.field.last, error.message))
42
+ end
43
+
44
+ @ctx.puts(@ctx.message('push.push_with_errors_info'))
45
+ end
46
+
47
+ def format_time(time)
48
+ time.utc.strftime(TIME_DISPLAY_FORMAT)
49
+ end
50
+
51
+ def with_waiting_text
52
+ @ctx.puts(@ctx.message('push.waiting_text'))
53
+ yield
54
+ end
55
+
56
+ def update_draft
57
+ with_waiting_text do
58
+ Tasks::UpdateDraft.call(
59
+ context: @ctx,
60
+ api_key: project.app.api_key,
61
+ registration_id: project.registration_id,
62
+ config: extension_type.config(@ctx),
63
+ extension_context: extension_type.extension_context(@ctx)
64
+ )
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Commands
5
+ class Register < ExtensionCommand
6
+ options do |parser, flags|
7
+ parser.on('--api_key=KEY') { |key| flags[:api_key] = key.downcase }
8
+ end
9
+
10
+ def call(args, _command_name)
11
+ CLI::UI::Frame.open(@ctx.message('register.frame_title')) do
12
+ @ctx.abort(@ctx.message('register.already_registered')) if project.registered?
13
+
14
+ with_register_form(args) do |form|
15
+ should_continue = confirm_registration(form.app)
16
+ registration = should_continue ? register_extension(form.app) : abort_not_registered
17
+
18
+ update_project_files(form.app, registration)
19
+
20
+ @ctx.puts(@ctx.message('register.success', project.title, form.app.title))
21
+ @ctx.puts(@ctx.message('register.success_info'))
22
+ end
23
+ end
24
+ end
25
+
26
+ def self.help
27
+ <<~HELP
28
+ Register your local extension to a Shopify app
29
+ Usage: {{command:#{ShopifyCli::TOOL_NAME} register}}
30
+ Options:
31
+ {{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.
32
+ HELP
33
+ end
34
+
35
+ private
36
+
37
+ def with_register_form(args)
38
+ form = Forms::Register.ask(@ctx, args, options.flags)
39
+ return @ctx.puts(self.class.help) if form.nil?
40
+
41
+ yield form
42
+ end
43
+
44
+ def confirm_registration(app)
45
+ @ctx.puts(@ctx.message('register.confirm_info', extension_type.name))
46
+ CLI::UI::Prompt.confirm(@ctx.message('register.confirm_question', app.title))
47
+ end
48
+
49
+ def register_extension(app)
50
+ @ctx.puts(@ctx.message('register.waiting_text'))
51
+
52
+ Tasks::CreateExtension.call(
53
+ context: @ctx,
54
+ api_key: app.api_key,
55
+ type: extension_type.identifier,
56
+ title: project.title,
57
+ config: {},
58
+ extension_context: extension_type.extension_context(@ctx)
59
+ )
60
+ end
61
+
62
+ def update_project_files(app, registration)
63
+ ExtensionProject.write_env_file(
64
+ context: @ctx,
65
+ api_key: app.api_key,
66
+ api_secret: app.secret,
67
+ registration_id: registration.id,
68
+ title: project.title
69
+ )
70
+ end
71
+
72
+ def abort_not_registered
73
+ @ctx.puts(@ctx.message('register.confirm_abort'))
74
+ raise ShopifyCli::AbortSilent
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Commands
5
+ class Serve < ExtensionCommand
6
+ YARN_SERVE_COMMAND = %w(server)
7
+ NPM_SERVE_COMMAND = %w(run-script server)
8
+
9
+ def call(_args, _command_name)
10
+ CLI::UI::Frame.open(@ctx.message('serve.frame_title')) do
11
+ success = ShopifyCli::JsSystem.call(@ctx, yarn: YARN_SERVE_COMMAND, npm: NPM_SERVE_COMMAND)
12
+ @ctx.abort(@ctx.message('serve.serve_failure_message')) unless success
13
+ end
14
+ end
15
+
16
+ def self.help
17
+ <<~HELP
18
+ Serve your extension in a local simulator for development.
19
+ Usage: {{command:#{ShopifyCli::TOOL_NAME} serve}}
20
+ HELP
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+ require 'shopify_cli'
3
+
4
+ module Extension
5
+ module Commands
6
+ class Tunnel < ExtensionCommand
7
+ options do |parser, flags|
8
+ parser.on('--port=PORT') { |port| flags[:port] = port }
9
+ end
10
+
11
+ AUTH_SUBCOMMAND = 'auth'
12
+ START_SUBCOMMAND = 'start'
13
+ STOP_SUBCOMMAND = 'stop'
14
+ STATUS_SUBCOMMAND = 'status'
15
+ DEFAULT_PORT = 39351
16
+
17
+ def call(args, _name)
18
+ subcommand = args.shift
19
+
20
+ case subcommand
21
+ when AUTH_SUBCOMMAND then authorize(args)
22
+ when START_SUBCOMMAND then ShopifyCli::Tunnel.start(@ctx, port: port)
23
+ when STOP_SUBCOMMAND then ShopifyCli::Tunnel.stop(@ctx)
24
+ when STATUS_SUBCOMMAND then status
25
+ else @ctx.puts(self.class.help)
26
+ end
27
+ end
28
+
29
+ def self.help
30
+ ShopifyCli::Context.message('tunnel.help', ShopifyCli::TOOL_NAME)
31
+ end
32
+
33
+ def self.extended_help
34
+ ShopifyCli::Context.message('tunnel.extended_help', ShopifyCli::TOOL_NAME, DEFAULT_PORT)
35
+ end
36
+
37
+ private
38
+
39
+ def status
40
+ tunnel_url = Features::TunnelUrl.fetch
41
+
42
+ if tunnel_url.nil?
43
+ @ctx.puts(@ctx.message('tunnel.no_tunnel_running'))
44
+ else
45
+ @ctx.puts(@ctx.message('tunnel.tunnel_running_at', tunnel_url))
46
+ end
47
+ end
48
+
49
+ def port
50
+ return DEFAULT_PORT unless options.flags.key?(:port)
51
+
52
+ port = options.flags[:port].to_i
53
+ @ctx.abort(@ctx.message('tunnel.invalid_port', options.flags[:port])) unless port > 0
54
+ port
55
+ end
56
+
57
+ def authorize(args)
58
+ token = args.shift
59
+
60
+ if token.nil?
61
+ @ctx.puts(@ctx.message('tunnel.missing_token'))
62
+ @ctx.puts("#{self.class.help}\n#{self.class.extended_help}")
63
+ else
64
+ ShopifyCli::Tunnel.auth(@ctx, token)
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+ require 'shopify_cli'
3
+
4
+ module Extension
5
+ class ExtensionProject < ShopifyCli::Project
6
+ class << self
7
+ def write_cli_file(context:, type:)
8
+ ShopifyCli::Project.write(
9
+ context,
10
+ project_type: :extension,
11
+ organization_id: nil,
12
+ "#{ExtensionProjectKeys::EXTENSION_TYPE_KEY}": type
13
+ )
14
+ end
15
+
16
+ def write_env_file(context:, title:, api_key: '', api_secret: '', registration_id: nil)
17
+ ShopifyCli::Resources::EnvFile.new(
18
+ api_key: api_key,
19
+ secret: api_secret,
20
+ extra: {
21
+ ExtensionProjectKeys::TITLE_KEY => title,
22
+ ExtensionProjectKeys::REGISTRATION_ID_KEY => registration_id,
23
+ }.compact
24
+ ).write(context)
25
+
26
+ current.reload unless project_empty?
27
+ end
28
+
29
+ private
30
+
31
+ def project_empty?
32
+ directory(Dir.pwd).nil?
33
+ end
34
+ end
35
+
36
+ def app
37
+ Models::App.new(api_key: env['api_key'], secret: env['secret'])
38
+ end
39
+
40
+ def registered?
41
+ property_present?('api_key') && property_present?('secret') && registration_id?
42
+ end
43
+
44
+ def title
45
+ get_extra_field(ExtensionProjectKeys::TITLE_KEY)
46
+ end
47
+
48
+ def extension_type_identifier
49
+ config[ExtensionProjectKeys::EXTENSION_TYPE_KEY]
50
+ end
51
+
52
+ def registration_id?
53
+ extra_property_present?(ExtensionProjectKeys::REGISTRATION_ID_KEY) &&
54
+ integer?(get_extra_field(ExtensionProjectKeys::REGISTRATION_ID_KEY)) &&
55
+ registration_id > 0
56
+ end
57
+
58
+ def registration_id
59
+ get_extra_field(ExtensionProjectKeys::REGISTRATION_ID_KEY).to_i
60
+ end
61
+
62
+ def reload
63
+ @env = nil
64
+ end
65
+
66
+ private
67
+
68
+ def get_extra_field(key)
69
+ extra = env[:extra] || {}
70
+ extra[key]
71
+ end
72
+
73
+ def extra_property_present?(key)
74
+ env[:extra].key?(key) && !get_extra_field(key).nil?
75
+ end
76
+
77
+ def property_present?(key)
78
+ !env[key].nil? && !env[key].strip.empty?
79
+ end
80
+
81
+ def integer?(value)
82
+ value.to_i.to_s == value.to_s
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+ require 'shopify_cli'
3
+
4
+ module Extension
5
+ module ExtensionProjectKeys
6
+ REGISTRATION_ID_KEY = 'EXTENSION_ID'
7
+ EXTENSION_TYPE_KEY = 'EXTENSION_TYPE'
8
+ TITLE_KEY = 'EXTENSION_TITLE'
9
+ end
10
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+ require 'base64'
3
+
4
+ module Extension
5
+ module Features
6
+ class Argo
7
+ include SmartProperties
8
+
9
+ GIT_ADMIN_TEMPLATE = 'https://github.com/Shopify/argo-admin-template.git'
10
+ GIT_CHECKOUT_TEMPLATE = 'https://github.com/Shopify/argo-checkout-template.git'
11
+ SCRIPT_PATH = %w(build main.js).freeze
12
+
13
+ class << self
14
+ def admin
15
+ @admin ||= Argo.new(setup: ArgoSetup.new(git_template: GIT_ADMIN_TEMPLATE))
16
+ end
17
+
18
+ def checkout
19
+ @checkout ||= Argo.new(
20
+ setup: ArgoSetup.new(
21
+ git_template: GIT_CHECKOUT_TEMPLATE,
22
+ dependency_checks: [ArgoDependencies.node_installed(min_major: 10, min_minor: 16)]
23
+ )
24
+ )
25
+ end
26
+ end
27
+
28
+ property! :setup, accepts: Features::ArgoSetup
29
+
30
+ def create(directory_name, identifier, context)
31
+ setup.call(directory_name, identifier, context)
32
+ end
33
+
34
+ def config(context)
35
+ filepath = File.join(context.root, SCRIPT_PATH)
36
+ context.abort(context.message('features.argo.missing_file_error')) unless File.exist?(filepath)
37
+
38
+ begin
39
+ {
40
+ serialized_script: Base64.strict_encode64(File.open(filepath).read.chomp),
41
+ }
42
+ rescue StandardError
43
+ context.abort(context.message('features.argo.script_prepare_error'))
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end