shopify-cli 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Features
5
+ class ArgoDependencies
6
+ def self.node_installed(min_major:, min_minor: nil)
7
+ -> (context) do
8
+ out, status = CLI::Kit::System.capture2('node', '-v')
9
+ context.abort(context.message('features.argo.dependencies.node.node_not_installed')) unless status.success?
10
+
11
+ min_version = 'v' + min_major .to_s + '.' + (min_minor.nil? ? 'x' : min_minor.to_s) + '.x'
12
+ version = out.strip
13
+ parsed_version = version.match(/v(?<major>\d+).(?<minor>\d+).(?<patch>\d+)/)
14
+
15
+ unless min_major.nil? || parsed_version[:major].to_i >= min_major
16
+ context.abort(context.message('features.argo.dependencies.node.version_too_low', version, min_version))
17
+ end
18
+
19
+ return if parsed_version[:major].to_i > min_major
20
+
21
+ unless min_minor.nil? || parsed_version[:minor].to_i >= min_minor
22
+ context.abort(context.message('features.argo.dependencies.node.version_too_low', version, min_version))
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Features
5
+ class ArgoSetup
6
+ include SmartProperties
7
+
8
+ GIT_DIRECTORY = '.git'
9
+ SCRIPTS_DIRECTORY = 'scripts'
10
+
11
+ property! :git_template, accepts: String
12
+ property! :dependency_checks, default: []
13
+
14
+ def call(directory_name, identifier, context)
15
+ steps = [
16
+ ArgoSetupSteps.check_dependencies(dependency_checks),
17
+ ArgoSetupSteps.clone_template(git_template),
18
+ ArgoSetupSteps.install_dependencies,
19
+ ArgoSetupSteps.initialize_project,
20
+ ]
21
+
22
+ install_result = run_install_steps(context, steps, identifier, directory_name)
23
+
24
+ cleanup(context, install_result, directory_name)
25
+ install_result
26
+ end
27
+
28
+ def run_install_steps(context, steps, identifier, directory_name)
29
+ system = ShopifyCli::JsSystem.new(ctx: context)
30
+
31
+ steps.inject(true) do |success, setup_step|
32
+ success && setup_step.call(context, identifier, directory_name, system)
33
+ end
34
+ end
35
+
36
+ def cleanup(context, install_result, directory_name)
37
+ install_result ? cleanup_template(context) : cleanup_on_failure(context, directory_name)
38
+ end
39
+
40
+ def cleanup_template(context)
41
+ context.rm_r(GIT_DIRECTORY)
42
+ context.rm_r(SCRIPTS_DIRECTORY)
43
+ rescue Errno::ENOENT => e
44
+ context.debug(e)
45
+ end
46
+
47
+ def cleanup_on_failure(context, directory_name)
48
+ FileUtils.rm_r(directory_name) if Dir.exist?(directory_name)
49
+ rescue Errno::ENOENT => e
50
+ context.debug(e)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Features
5
+ class ArgoSetupStep
6
+ include SmartProperties
7
+
8
+ property! :step
9
+ property! :can_fail, accepts: [true, false], reader: :can_fail?
10
+
11
+ def call(context, identifier, directory_name, js_system)
12
+ step_result = step.call(context, identifier, directory_name, js_system)
13
+ can_fail? ? step_result : true
14
+ rescue ShopifyCli::Abort => e
15
+ context.puts(e.message)
16
+ false
17
+ rescue StandardError => e
18
+ context.puts("{{x}} #{e.message}")
19
+ false
20
+ end
21
+
22
+ def self.default(&block)
23
+ ArgoSetupStep.new(step: block, can_fail: true)
24
+ end
25
+
26
+ def self.always_successful(&block)
27
+ ArgoSetupStep.new(step: block, can_fail: false)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Features
5
+ module ArgoSetupSteps
6
+ YARN_INITIALIZE_COMMAND = %w(generate).freeze
7
+ NPM_INITIALIZE_COMMAND = %w(run generate --).freeze
8
+ INITIALIZE_TYPE_PARAMETER = '--type=%s'
9
+
10
+ def self.check_dependencies(dependency_checks)
11
+ ArgoSetupStep.always_successful do |context, _identifier, _directory_name, _js_system|
12
+ dependency_checks.each do |dependency_check|
13
+ dependency_check.call(context)
14
+ end
15
+ end
16
+ end
17
+
18
+ def self.clone_template(git_template)
19
+ ArgoSetupStep.default do |context, _identifier, directory_name, _js_system|
20
+ begin
21
+ ShopifyCli::Git.clone(git_template, directory_name, ctx: context)
22
+ context.root = File.join(context.root, directory_name)
23
+ rescue StandardError
24
+ context.puts('{{x}} Unable to clone the repository.')
25
+ end
26
+ end
27
+ end
28
+
29
+ def self.install_dependencies
30
+ ArgoSetupStep.default do |context, _identifier, _directory_name, js_system|
31
+ ShopifyCli::JsDeps.new(ctx: context, system: js_system).install
32
+ end
33
+ end
34
+
35
+ def self.initialize_project
36
+ ArgoSetupStep.default do |context, identifier, _directory_name, js_system|
37
+ frame_title = context.message('create.setup_project_frame_title')
38
+ failure_message = context.message('features.argo.initialization_error')
39
+
40
+ result = true
41
+ CLI::UI::Frame.open(frame_title, failure_text: failure_message) do
42
+ result = js_system.call(
43
+ yarn: YARN_INITIALIZE_COMMAND + [INITIALIZE_TYPE_PARAMETER % identifier],
44
+ npm: NPM_INITIALIZE_COMMAND + [INITIALIZE_TYPE_PARAMETER % identifier]
45
+ )
46
+ end
47
+
48
+ result
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ require 'base64'
3
+
4
+ module Extension
5
+ module Features
6
+ module TunnelUrl
7
+ NGROK_TUNNELS_URI = URI.parse('http://localhost:4040/api/tunnels')
8
+ TUNNELS_FIELD = 'tunnels'
9
+ PUBLIC_URL_FIELD = 'public_url'
10
+
11
+ def self.fetch
12
+ response = Net::HTTP.get_response(NGROK_TUNNELS_URI)
13
+ json = JSON.parse(response.body)
14
+ json.dig(TUNNELS_FIELD, 0, PUBLIC_URL_FIELD)
15
+ rescue
16
+ nil
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Forms
5
+ class Create < ShopifyCli::Form
6
+ flag_arguments :name, :type
7
+
8
+ def ask
9
+ self.type = ask_type
10
+ self.name = ask_name
11
+ end
12
+
13
+ def directory_name
14
+ @directory_name ||= name.strip.gsub(/( )/, '_').downcase
15
+ end
16
+
17
+ private
18
+
19
+ def ask_name
20
+ ask_with_reprompt(
21
+ initial_value: name,
22
+ break_condition: -> (current_name) { Models::Registration.valid_title?(current_name) },
23
+ prompt_message: ctx.message('create.ask_name'),
24
+ reprompt_message: ctx.message('create.invalid_name', Models::Registration::MAX_TITLE_LENGTH)
25
+ )
26
+ end
27
+
28
+ def ask_type
29
+ return Models::Type.load_type(type) if Models::Type.valid?(type)
30
+ ctx.puts(ctx.message('create.invalid_type')) unless type.nil?
31
+
32
+ CLI::UI::Prompt.ask(ctx.message('create.ask_type')) do |handler|
33
+ Models::Type.repository.values.each do |type|
34
+ handler.option("#{type.name} #{type.tagline}") { type }
35
+ end
36
+ end
37
+ end
38
+
39
+ def ask_with_reprompt(initial_value:, break_condition:, prompt_message:, reprompt_message:)
40
+ value = initial_value
41
+ reprompt = false
42
+
43
+ until break_condition.call(value)
44
+ ctx.puts(reprompt_message) if reprompt
45
+ value = CLI::UI::Prompt.ask(prompt_message)&.strip
46
+ reprompt = true
47
+ end
48
+ value
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Forms
5
+ class Register < ShopifyCli::Form
6
+ flag_arguments :api_key
7
+
8
+ attr_reader :app
9
+
10
+ def ask
11
+ self.app = ask_app
12
+ end
13
+
14
+ private
15
+
16
+ attr_writer :app
17
+
18
+ def ask_app
19
+ apps = load_apps
20
+
21
+ if !api_key.nil?
22
+ found_app = apps.find { |app| app.api_key == api_key }
23
+ ctx.abort(ctx.message('register.invalid_api_key', api_key)) if found_app.nil?
24
+ found_app
25
+ else
26
+ CLI::UI::Prompt.ask(ctx.message('register.ask_app')) do |handler|
27
+ apps.each do |app|
28
+ handler.option("#{app.title} by #{app.business_name}") { app }
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ def load_apps
35
+ ctx.puts(@ctx.message('register.loading_apps'))
36
+ apps = Tasks::GetApps.call(context: ctx)
37
+
38
+ apps.empty? ? abort_no_apps : apps
39
+ end
40
+
41
+ def abort_no_apps
42
+ ctx.puts(@ctx.message('register.no_apps'))
43
+ ctx.puts(@ctx.message('register.learn_about_apps'))
44
+ raise ShopifyCli::AbortSilent
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Extension
4
+ module Messages
5
+ module MessageLoading
6
+ def self.load
7
+ type_specific_messages = load_current_type_messages
8
+ return Messages::MESSAGES if type_specific_messages.nil?
9
+
10
+ if type_specific_messages.key?(:overrides)
11
+ deep_merge(Messages::MESSAGES, type_specific_messages[:overrides])
12
+ else
13
+ Messages::MESSAGES
14
+ end
15
+ end
16
+
17
+ def self.load_current_type_messages
18
+ return unless ShopifyCli::Project.has_current?
19
+ messages_for_type(ShopifyCli::Project.current.config[Extension::ExtensionProjectKeys::EXTENSION_TYPE_KEY])
20
+ end
21
+
22
+ def self.messages_for_type(type_identifier)
23
+ return if type_identifier.nil?
24
+
25
+ type_identifier_symbol = type_identifier.downcase.to_sym
26
+ return unless Messages::TYPES.key?(type_identifier_symbol)
27
+
28
+ TYPES[type_identifier_symbol]
29
+ end
30
+
31
+ def self.deep_merge(first, second)
32
+ merger = proc { |_key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
33
+ first.merge(second, &merger)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+ require 'shopify_cli'
3
+
4
+ module Extension
5
+ module Messages
6
+ MESSAGES = {
7
+ create: {
8
+ ask_name: 'Extension name',
9
+ invalid_name: 'Extension name must be under %s characters',
10
+ ask_type: 'What type of extension are you creating?',
11
+ invalid_type: 'Extension type is invalid.',
12
+ setup_project_frame_title: 'Initializing project',
13
+ ready_to_start: <<~MESSAGE,
14
+ {{v}} A new folder was generated at {{green:./%s}}.
15
+ {{*}} You’re ready to start building {{green:%s}}!
16
+ Navigate to the new folder, then run {{command:shopify serve}} to start a local server.
17
+ MESSAGE
18
+ learn_more: <<~MESSAGE,
19
+ {{*}} Once you're ready to version and publish your extension,
20
+ run {{command:shopify register}} to register this extension with one of your apps.
21
+ MESSAGE
22
+ try_again: '{{*}} Fix the errors and run {{command:shopify create extension}} again.',
23
+ errors: {
24
+ directory_exists: 'Directory ‘%s’ already exists. Please remove it or choose a new name for your project.',
25
+ },
26
+ },
27
+ build: {
28
+ frame_title: 'Building extension with: %s...',
29
+ build_failure_message: 'Failed to build extension code.',
30
+ },
31
+ register: {
32
+ frame_title: 'Registering Extension',
33
+ waiting_text: 'Registering with Shopify...',
34
+ already_registered: 'Extension is already registered.',
35
+ loading_apps: 'Loading your apps...',
36
+ ask_app: 'Which app would you like to register this extension with?',
37
+ no_apps: '{{x}} You don’t have any apps.',
38
+ learn_about_apps: '{{*}} Learn more about building apps at <https://shopify.dev/concepts/apps>, ' \
39
+ 'or try creating a new app using {{command:shopify create}}.',
40
+ invalid_api_key: 'The API key %s does not match any of your apps.',
41
+ confirm_info: 'This will create a new extension registration for %s, which can’t be undone.',
42
+ confirm_question: 'Would you like to register this extension with {{green:%s}}? (y/n)',
43
+ confirm_abort: 'Extension was not registered.',
44
+ success: '{{v}} Registered {{green:%s}} with {{green:%s}}.',
45
+ success_info: '{{*}} Run {{command:shopify push}} to push your extension to Shopify.',
46
+ },
47
+ push: {
48
+ frame_title: 'Pushing your extension to Shopify',
49
+ waiting_text: 'Pushing code to Shopify...',
50
+ pushed_with_errors: '{{x}} Code pushed to Shopify with errors on %s.',
51
+ push_with_errors_info: '{{*}} Fix these errors and run {{command:shopify push}} to revalidate your extension.',
52
+ success_confirmation: '{{v}} Pushed {{green:%s}} to a draft on %s.',
53
+ success_info: '{{*}} Visit %s to version and publish your extension.',
54
+ },
55
+ serve: {
56
+ frame_title: 'Serving extension...',
57
+ serve_failure_message: 'Failed to run extension code.',
58
+ },
59
+ tunnel: {
60
+ missing_token: '{{x}} {{red:auth requires a token argument}}. '\
61
+ 'Find it on your ngrok dashboard: {{underline:https://dashboard.ngrok.com/auth/your-authtoken}}.',
62
+ invalid_port: '%s is not a valid port.',
63
+ no_tunnel_running: 'No tunnel running.',
64
+ tunnel_running_at: 'Tunnel running at: {{underline:%s}}',
65
+ help: <<~HELP,
66
+ Start or stop an http tunnel to your local development extension using ngrok.
67
+ Usage: {{command:%s tunnel [ auth | start | stop | status ]}}
68
+ HELP
69
+ extended_help: <<~HELP,
70
+ {{bold:Subcommands:}}
71
+
72
+ {{cyan:auth}}: Writes an ngrok auth token to ~/.ngrok2/ngrok.yml to connect with an ngrok account.
73
+ Visit https://dashboard.ngrok.com/signup to sign up.
74
+ Usage: {{command:%1$s tunnel auth <token>}}
75
+
76
+ {{cyan:start}}: Starts an ngrok tunnel, will print the URL for an existing tunnel if already running.
77
+ Usage: {{command:%1$s tunnel start}}
78
+ Options:
79
+ {{command:--port=PORT}} Forward the ngrok subdomain to local port PORT. Defaults to %2$s.
80
+
81
+ {{cyan:stop}}: Stops the ngrok tunnel.
82
+ Usage: {{command:%1$s tunnel stop}}
83
+
84
+ {{cyan:status}}: Output the current status of the ngrok tunnel.
85
+ Usage: {{command:%1$s tunnel status}}
86
+ HELP
87
+ },
88
+ features: {
89
+ argo: {
90
+ missing_file_error: 'Could not find built extension file.',
91
+ script_prepare_error: 'An error occurred while attempting to prepare your script.',
92
+ initialization_error: '{{x}} There was an error while initializing the project.',
93
+ dependencies: {
94
+ node: {
95
+ node_not_installed: 'Node must be installed to create this extension.',
96
+ version_too_low: 'Your node version %s does not meet the minimum required version %s',
97
+ },
98
+ },
99
+ },
100
+ },
101
+ tasks: {
102
+ errors: {
103
+ parse_error: 'Unable to parse response from Partners Dashboard.',
104
+ },
105
+ },
106
+ errors: {
107
+ unknown_type: 'Unknown extension type %s',
108
+ },
109
+ }
110
+
111
+ TYPES = {
112
+ subscription_management: {
113
+ name: 'Subscription Management',
114
+ tagline: '(limit 1 per app)',
115
+ overrides: {
116
+ register: {
117
+ confirm_info: 'You can only create one %s extension per app, which can’t be undone.',
118
+ },
119
+ },
120
+ },
121
+ checkout_post_purchase: {
122
+ name: 'Checkout Post Purchase',
123
+ },
124
+ }
125
+ end
126
+ end