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,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