shopify-cli 1.5.0 → 1.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 (305) hide show
  1. checksums.yaml +4 -4
  2. data/.github/PULL_REQUEST_TEMPLATE.md +1 -0
  3. data/.rubocop_todo.yml +15 -2
  4. data/.travis.yml +1 -0
  5. data/CHANGELOG.md +26 -0
  6. data/Gemfile +12 -12
  7. data/Gemfile.lock +14 -14
  8. data/README.md +39 -7
  9. data/Rakefile +32 -28
  10. data/bin/load_shopify.rb +6 -6
  11. data/bin/shopify +2 -2
  12. data/dev.yml +5 -2
  13. data/docs/_config.yml +1 -18
  14. data/docs/app/node/commands/index.md +2 -80
  15. data/docs/app/node/index.md +2 -33
  16. data/docs/app/rails/commands/index.md +2 -78
  17. data/docs/app/rails/index.md +2 -34
  18. data/docs/core/index.md +2 -84
  19. data/docs/getting-started/index.md +2 -25
  20. data/docs/getting-started/install/index.md +1 -118
  21. data/docs/getting-started/migrate/index.md +2 -94
  22. data/docs/getting-started/uninstall/index.md +2 -35
  23. data/docs/getting-started/upgrade/index.md +2 -39
  24. data/docs/help/start-app/index.md +2 -4
  25. data/docs/index.md +2 -24
  26. data/ext/shopify-cli/extconf.rb +7 -7
  27. data/install.sh +1 -1
  28. data/lib/docgen/markdown.rb +12 -12
  29. data/lib/graphql/extension_create.graphql +17 -2
  30. data/lib/graphql/fetch_specifications.graphql +14 -0
  31. data/lib/{project_types/extension/graphql → graphql}/get_app_by_api_key.graphql +0 -0
  32. data/lib/project_types/extension/cli.rb +56 -48
  33. data/lib/project_types/extension/commands/build.rb +3 -3
  34. data/lib/project_types/extension/commands/create.rb +17 -10
  35. data/lib/project_types/extension/commands/extension_command.rb +14 -7
  36. data/lib/project_types/extension/commands/push.rb +10 -10
  37. data/lib/project_types/extension/commands/register.rb +22 -32
  38. data/lib/project_types/extension/commands/serve.rb +1 -7
  39. data/lib/project_types/extension/commands/tunnel.rb +12 -12
  40. data/lib/project_types/extension/extension_project.rb +22 -7
  41. data/lib/project_types/extension/extension_project_keys.rb +5 -4
  42. data/lib/project_types/extension/features/argo.rb +123 -0
  43. data/lib/project_types/extension/features/argo_config.rb +5 -5
  44. data/lib/project_types/extension/features/argo_dependencies.rb +5 -5
  45. data/lib/project_types/extension/features/argo_renderer_package.rb +32 -0
  46. data/lib/project_types/extension/features/argo_serve.rb +69 -0
  47. data/lib/project_types/extension/features/argo_setup.rb +2 -2
  48. data/lib/project_types/extension/features/argo_setup_steps.rb +4 -4
  49. data/lib/project_types/extension/forms/create.rb +28 -34
  50. data/lib/project_types/extension/forms/questions/ask_app.rb +53 -0
  51. data/lib/project_types/extension/forms/questions/ask_name.rb +40 -0
  52. data/lib/project_types/extension/forms/questions/ask_type.rb +47 -0
  53. data/lib/project_types/extension/messages/message_loading.rb +3 -1
  54. data/lib/project_types/extension/messages/messages.rb +55 -52
  55. data/lib/project_types/extension/models/lazy_specification_handler.rb +12 -0
  56. data/lib/project_types/extension/models/registration.rb +1 -0
  57. data/lib/project_types/extension/models/specification.rb +39 -0
  58. data/lib/project_types/extension/models/specification_handlers/checkout_post_purchase.rb +19 -0
  59. data/lib/project_types/extension/models/specification_handlers/default.rb +75 -0
  60. data/lib/project_types/extension/models/specifications.rb +88 -0
  61. data/lib/project_types/extension/tasks/configure_features.rb +54 -0
  62. data/lib/project_types/extension/tasks/converters/app_converter.rb +6 -6
  63. data/lib/project_types/extension/tasks/converters/registration_converter.rb +8 -6
  64. data/lib/project_types/extension/tasks/converters/validation_error_converter.rb +4 -4
  65. data/lib/project_types/extension/tasks/converters/version_converter.rb +7 -7
  66. data/lib/project_types/extension/tasks/create_extension.rb +4 -4
  67. data/lib/project_types/extension/tasks/fetch_specifications.rb +18 -0
  68. data/lib/project_types/extension/tasks/get_app.rb +4 -4
  69. data/lib/project_types/extension/tasks/get_apps.rb +3 -3
  70. data/lib/project_types/extension/tasks/update_draft.rb +4 -4
  71. data/lib/project_types/extension/tasks/user_errors.rb +4 -4
  72. data/lib/project_types/node/cli.rb +19 -19
  73. data/lib/project_types/node/commands/connect.rb +3 -3
  74. data/lib/project_types/node/commands/create.rb +42 -38
  75. data/lib/project_types/node/commands/deploy.rb +4 -4
  76. data/lib/project_types/node/commands/deploy/heroku.rb +24 -24
  77. data/lib/project_types/node/commands/generate.rb +3 -34
  78. data/lib/project_types/node/commands/open.rb +2 -2
  79. data/lib/project_types/node/commands/populate.rb +6 -6
  80. data/lib/project_types/node/commands/populate/customer.rb +5 -5
  81. data/lib/project_types/node/commands/populate/draft_order.rb +5 -5
  82. data/lib/project_types/node/commands/populate/product.rb +5 -5
  83. data/lib/project_types/node/commands/serve.rb +9 -9
  84. data/lib/project_types/node/commands/tunnel.rb +7 -7
  85. data/lib/project_types/node/forms/create.rb +17 -8
  86. data/lib/project_types/node/messages/messages.rb +13 -47
  87. data/lib/project_types/rails/cli.rb +21 -21
  88. data/lib/project_types/rails/commands/connect.rb +3 -3
  89. data/lib/project_types/rails/commands/create.rb +56 -54
  90. data/lib/project_types/rails/commands/deploy.rb +4 -4
  91. data/lib/project_types/rails/commands/deploy/heroku.rb +30 -30
  92. data/lib/project_types/rails/commands/generate.rb +7 -7
  93. data/lib/project_types/rails/commands/generate/webhook.rb +6 -6
  94. data/lib/project_types/rails/commands/open.rb +2 -2
  95. data/lib/project_types/rails/commands/populate.rb +6 -6
  96. data/lib/project_types/rails/commands/populate/customer.rb +5 -5
  97. data/lib/project_types/rails/commands/populate/draft_order.rb +5 -5
  98. data/lib/project_types/rails/commands/populate/product.rb +5 -5
  99. data/lib/project_types/rails/commands/serve.rb +11 -11
  100. data/lib/project_types/rails/commands/tunnel.rb +7 -7
  101. data/lib/project_types/rails/forms/create.rb +35 -25
  102. data/lib/project_types/rails/gem.rb +24 -24
  103. data/lib/project_types/rails/messages/messages.rb +6 -5
  104. data/lib/project_types/rails/ruby.rb +2 -2
  105. data/lib/project_types/script/cli.rb +38 -39
  106. data/lib/project_types/script/commands/create.rb +12 -14
  107. data/lib/project_types/script/commands/push.rb +10 -17
  108. data/lib/project_types/script/config/extension_points.yml +29 -10
  109. data/lib/project_types/script/errors.rb +1 -2
  110. data/lib/project_types/script/forms/create.rb +18 -5
  111. data/lib/project_types/script/graphql/app_script_update_or_create.graphql +9 -1
  112. data/lib/project_types/script/graphql/script_service_proxy.graphql +1 -2
  113. data/lib/project_types/script/layers/application/build_script.rb +10 -7
  114. data/lib/project_types/script/layers/application/create_script.rb +37 -25
  115. data/lib/project_types/script/layers/application/extension_points.rb +25 -0
  116. data/lib/project_types/script/layers/application/project_dependencies.rb +4 -4
  117. data/lib/project_types/script/layers/application/push_script.rb +13 -18
  118. data/lib/project_types/script/layers/domain/config_ui.rb +16 -0
  119. data/lib/project_types/script/layers/domain/errors.rb +20 -0
  120. data/lib/project_types/script/layers/domain/extension_point.rb +82 -11
  121. data/lib/project_types/script/layers/domain/metadata.rb +48 -0
  122. data/lib/project_types/script/layers/domain/push_package.rb +25 -6
  123. data/lib/project_types/script/layers/domain/script_project.rb +34 -0
  124. data/lib/project_types/script/layers/infrastructure/assemblyscript_project_creator.rb +42 -13
  125. data/lib/project_types/script/layers/infrastructure/assemblyscript_task_runner.rb +24 -49
  126. data/lib/project_types/script/layers/infrastructure/errors.rb +32 -19
  127. data/lib/project_types/script/layers/infrastructure/extension_point_repository.rb +12 -6
  128. data/lib/project_types/script/layers/infrastructure/project_creator.rb +2 -1
  129. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +22 -17
  130. data/lib/project_types/script/layers/infrastructure/rust_project_creator.rb +72 -0
  131. data/lib/project_types/script/layers/infrastructure/rust_task_runner.rb +59 -0
  132. data/lib/project_types/script/layers/infrastructure/script_project_repository.rb +145 -0
  133. data/lib/project_types/script/layers/infrastructure/script_service.rb +32 -75
  134. data/lib/project_types/script/layers/infrastructure/task_runner.rb +4 -3
  135. data/lib/project_types/script/messages/messages.rb +58 -59
  136. data/lib/project_types/script/ui/error_handler.rb +115 -72
  137. data/lib/project_types/script/ui/printing_spinner.rb +1 -1
  138. data/lib/project_types/script/ui/strict_spinner.rb +1 -1
  139. data/lib/project_types/theme/cli.rb +40 -0
  140. data/lib/project_types/theme/commands/connect.rb +54 -0
  141. data/lib/project_types/theme/commands/create.rb +48 -0
  142. data/lib/project_types/theme/commands/deploy.rb +38 -0
  143. data/lib/project_types/theme/commands/generate.rb +20 -0
  144. data/lib/project_types/theme/commands/generate/env.rb +79 -0
  145. data/lib/project_types/theme/commands/push.rb +55 -0
  146. data/lib/project_types/theme/commands/serve.rb +31 -0
  147. data/lib/project_types/theme/forms/connect.rb +34 -0
  148. data/lib/project_types/theme/forms/create.rb +22 -0
  149. data/lib/project_types/theme/messages/messages.rb +147 -0
  150. data/lib/project_types/theme/tasks/ensure_themekit_installed.rb +78 -0
  151. data/lib/project_types/theme/themekit.rb +113 -0
  152. data/lib/rubygems_plugin.rb +3 -3
  153. data/lib/shopify-cli/admin_api.rb +52 -12
  154. data/lib/shopify-cli/admin_api/populate_resource_command.rb +17 -17
  155. data/lib/shopify-cli/admin_api/schema.rb +3 -3
  156. data/lib/shopify-cli/api.rb +34 -31
  157. data/lib/shopify-cli/command.rb +1 -1
  158. data/lib/shopify-cli/commands.rb +9 -9
  159. data/lib/shopify-cli/commands/config.rb +28 -52
  160. data/lib/shopify-cli/commands/connect.rb +10 -10
  161. data/lib/shopify-cli/commands/create.rb +5 -5
  162. data/lib/shopify-cli/commands/help.rb +6 -6
  163. data/lib/shopify-cli/commands/logout.rb +3 -3
  164. data/lib/shopify-cli/commands/system.rb +33 -33
  165. data/lib/shopify-cli/commands/version.rb +2 -2
  166. data/lib/shopify-cli/context.rb +71 -22
  167. data/lib/shopify-cli/core.rb +4 -4
  168. data/lib/shopify-cli/core/entry_point.rb +5 -5
  169. data/lib/shopify-cli/core/executor.rb +1 -1
  170. data/lib/shopify-cli/core/help_resolver.rb +2 -2
  171. data/lib/shopify-cli/core/monorail.rb +16 -16
  172. data/lib/shopify-cli/db.rb +2 -2
  173. data/lib/shopify-cli/feature.rb +1 -3
  174. data/lib/shopify-cli/form.rb +1 -1
  175. data/lib/shopify-cli/git.rb +17 -17
  176. data/lib/shopify-cli/helpers.rb +1 -1
  177. data/lib/shopify-cli/helpers/haikunator.rb +1 -1
  178. data/lib/shopify-cli/heroku.rb +28 -28
  179. data/lib/shopify-cli/http_request.rb +21 -9
  180. data/lib/shopify-cli/js_deps.rb +12 -12
  181. data/lib/shopify-cli/js_system.rb +5 -5
  182. data/lib/shopify-cli/lazy_delegator.rb +55 -0
  183. data/lib/shopify-cli/messages/messages.rb +9 -16
  184. data/lib/shopify-cli/method_object.rb +104 -0
  185. data/lib/shopify-cli/oauth.rb +25 -25
  186. data/lib/shopify-cli/oauth/servlet.rb +9 -9
  187. data/lib/shopify-cli/options.rb +3 -3
  188. data/lib/shopify-cli/packager.rb +24 -24
  189. data/lib/shopify-cli/partners_api.rb +24 -18
  190. data/lib/shopify-cli/partners_api/organizations.rb +10 -10
  191. data/lib/shopify-cli/process_supervision.rb +7 -7
  192. data/lib/shopify-cli/project.rb +16 -16
  193. data/lib/shopify-cli/project_type.rb +4 -4
  194. data/lib/shopify-cli/resolve_constant.rb +25 -0
  195. data/lib/shopify-cli/resources.rb +1 -1
  196. data/lib/shopify-cli/resources/env_file.rb +9 -9
  197. data/lib/shopify-cli/result.rb +432 -0
  198. data/lib/shopify-cli/shopifolk.rb +6 -8
  199. data/lib/shopify-cli/sub_command.rb +1 -1
  200. data/lib/shopify-cli/task.rb +3 -3
  201. data/lib/shopify-cli/tasks.rb +7 -7
  202. data/lib/shopify-cli/tasks/create_api_client.rb +5 -5
  203. data/lib/shopify-cli/tasks/ensure_dev_store.rb +12 -12
  204. data/lib/shopify-cli/tasks/ensure_env.rb +15 -15
  205. data/lib/shopify-cli/tasks/ensure_loopback_url.rb +4 -4
  206. data/lib/shopify-cli/tasks/select_org_and_shop.rb +25 -24
  207. data/lib/shopify-cli/tasks/update_dashboard_urls.rb +10 -10
  208. data/lib/shopify-cli/transform_data_structure.rb +86 -0
  209. data/lib/shopify-cli/tunnel.rb +36 -30
  210. data/lib/shopify-cli/version.rb +1 -1
  211. data/lib/shopify_cli.rb +57 -52
  212. data/shopify-cli.gemspec +6 -6
  213. data/shopify.fish +1 -1
  214. data/shopify.sh +1 -1
  215. data/vendor/deps/cli-kit/REVISION +1 -1
  216. data/vendor/deps/cli-kit/lib/cli/kit/logger.rb +2 -2
  217. data/vendor/deps/cli-kit/lib/cli/kit/system.rb +3 -3
  218. data/vendor/deps/cli-ui/REVISION +1 -1
  219. data/vendor/deps/cli-ui/lib/cli/ui.rb +26 -22
  220. data/vendor/deps/cli-ui/lib/cli/ui/ansi.rb +4 -6
  221. data/vendor/deps/cli-ui/lib/cli/ui/frame.rb +3 -3
  222. data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_stack.rb +8 -9
  223. data/vendor/deps/cli-ui/lib/cli/ui/frame/frame_style.rb +1 -1
  224. data/vendor/deps/cli-ui/lib/cli/ui/glyph.rb +1 -0
  225. data/vendor/deps/cli-ui/lib/cli/ui/printer.rb +15 -3
  226. data/vendor/deps/cli-ui/lib/cli/ui/prompt/interactive_options.rb +4 -11
  227. data/vendor/deps/cli-ui/lib/cli/ui/spinner.rb +3 -5
  228. data/vendor/deps/cli-ui/lib/cli/ui/terminal.rb +10 -10
  229. data/vendor/deps/cli-ui/lib/cli/ui/version.rb +1 -1
  230. data/vendor/deps/cli-ui/lib/cli/ui/wrap.rb +56 -0
  231. data/vendor/deps/webrick/.gitignore +9 -0
  232. data/vendor/deps/webrick/Gemfile +3 -0
  233. data/vendor/deps/webrick/LICENSE.txt +22 -0
  234. data/vendor/deps/webrick/README.md +61 -0
  235. data/vendor/deps/webrick/Rakefile +10 -0
  236. data/vendor/deps/webrick/lib/webrick.rb +232 -0
  237. data/vendor/deps/webrick/lib/webrick/accesslog.rb +157 -0
  238. data/vendor/deps/webrick/lib/webrick/cgi.rb +313 -0
  239. data/vendor/deps/webrick/lib/webrick/compat.rb +36 -0
  240. data/vendor/deps/webrick/lib/webrick/config.rb +158 -0
  241. data/vendor/deps/webrick/lib/webrick/cookie.rb +172 -0
  242. data/vendor/deps/webrick/lib/webrick/htmlutils.rb +30 -0
  243. data/vendor/deps/webrick/lib/webrick/httpauth.rb +96 -0
  244. data/vendor/deps/webrick/lib/webrick/httpauth/authenticator.rb +117 -0
  245. data/vendor/deps/webrick/lib/webrick/httpauth/basicauth.rb +116 -0
  246. data/vendor/deps/webrick/lib/webrick/httpauth/digestauth.rb +395 -0
  247. data/vendor/deps/webrick/lib/webrick/httpauth/htdigest.rb +132 -0
  248. data/vendor/deps/webrick/lib/webrick/httpauth/htgroup.rb +97 -0
  249. data/vendor/deps/webrick/lib/webrick/httpauth/htpasswd.rb +158 -0
  250. data/vendor/deps/webrick/lib/webrick/httpauth/userdb.rb +53 -0
  251. data/vendor/deps/webrick/lib/webrick/httpproxy.rb +354 -0
  252. data/vendor/deps/webrick/lib/webrick/httprequest.rb +636 -0
  253. data/vendor/deps/webrick/lib/webrick/httpresponse.rb +564 -0
  254. data/vendor/deps/webrick/lib/webrick/https.rb +152 -0
  255. data/vendor/deps/webrick/lib/webrick/httpserver.rb +294 -0
  256. data/vendor/deps/webrick/lib/webrick/httpservlet.rb +23 -0
  257. data/vendor/deps/webrick/lib/webrick/httpservlet/abstract.rb +152 -0
  258. data/vendor/deps/webrick/lib/webrick/httpservlet/cgi_runner.rb +47 -0
  259. data/vendor/deps/webrick/lib/webrick/httpservlet/cgihandler.rb +126 -0
  260. data/vendor/deps/webrick/lib/webrick/httpservlet/erbhandler.rb +88 -0
  261. data/vendor/deps/webrick/lib/webrick/httpservlet/filehandler.rb +552 -0
  262. data/vendor/deps/webrick/lib/webrick/httpservlet/prochandler.rb +47 -0
  263. data/vendor/deps/webrick/lib/webrick/httpstatus.rb +194 -0
  264. data/vendor/deps/webrick/lib/webrick/httputils.rb +512 -0
  265. data/vendor/deps/webrick/lib/webrick/httpversion.rb +76 -0
  266. data/vendor/deps/webrick/lib/webrick/log.rb +156 -0
  267. data/vendor/deps/webrick/lib/webrick/server.rb +381 -0
  268. data/vendor/deps/webrick/lib/webrick/ssl.rb +215 -0
  269. data/vendor/deps/webrick/lib/webrick/utils.rb +265 -0
  270. data/vendor/deps/webrick/lib/webrick/version.rb +18 -0
  271. data/vendor/deps/webrick/webrick.gemspec +74 -0
  272. data/vendor/gen/template/bin/update-deps +9 -9
  273. metadata +83 -35
  274. data/docs/Gemfile +0 -5
  275. data/docs/Gemfile.lock +0 -258
  276. data/docs/_data/nav.yml +0 -35
  277. data/docs/_includes/footer.html +0 -15
  278. data/docs/_includes/head.html +0 -19
  279. data/docs/_includes/sidebar_nav.html +0 -22
  280. data/docs/_includes/toc.html +0 -112
  281. data/docs/_layouts/default.html +0 -79
  282. data/docs/css/docs.css +0 -157
  283. data/docs/images/header.png +0 -0
  284. data/docs/installing-ruby.md +0 -28
  285. data/lib/project_types/extension/features/argo/admin.rb +0 -20
  286. data/lib/project_types/extension/features/argo/base.rb +0 -129
  287. data/lib/project_types/extension/features/argo/checkout.rb +0 -20
  288. data/lib/project_types/extension/forms/register.rb +0 -47
  289. data/lib/project_types/extension/models/type.rb +0 -81
  290. data/lib/project_types/extension/models/types/checkout_post_purchase.rb +0 -23
  291. data/lib/project_types/extension/models/types/product_subscription.rb +0 -24
  292. data/lib/project_types/node/commands/generate/billing.rb +0 -39
  293. data/lib/project_types/node/commands/generate/page.rb +0 -59
  294. data/lib/project_types/node/commands/generate/webhook.rb +0 -37
  295. data/lib/project_types/script/commands/disable.rb +0 -25
  296. data/lib/project_types/script/commands/enable.rb +0 -78
  297. data/lib/project_types/script/graphql/shop_script_delete.graphql +0 -14
  298. data/lib/project_types/script/graphql/shop_script_update_or_create.graphql +0 -28
  299. data/lib/project_types/script/layers/application/disable_script.rb +0 -21
  300. data/lib/project_types/script/layers/application/enable_script.rb +0 -23
  301. data/lib/project_types/script/layers/domain/script.rb +0 -18
  302. data/lib/project_types/script/layers/infrastructure/script_repository.rb +0 -47
  303. data/lib/project_types/script/script_project.rb +0 -54
  304. data/lib/project_types/script/templates/ts/as-pect.config.js +0 -27
  305. data/lib/project_types/script/templates/ts/as-pect.d.ts +0 -1
@@ -5,10 +5,10 @@ module ShopifyCli
5
5
  # The Shopifolk Feature flag will persist between runs so if the flag is enabled or disabled,
6
6
  # it will still be in that same state until the next class invocation.
7
7
  class Shopifolk
8
- GCLOUD_CONFIG_FILE = File.expand_path('~/.config/gcloud/configurations/config_default')
9
- DEV_PATH = '/opt/dev'
10
- SECTION = 'core'
11
- FEATURE_NAME = 'shopifolk'
8
+ GCLOUD_CONFIG_FILE = File.expand_path("~/.config/gcloud/configurations/config_default")
9
+ DEV_PATH = "/opt/dev"
10
+ SECTION = "core"
11
+ FEATURE_NAME = "shopifolk"
12
12
 
13
13
  class << self
14
14
  attr_writer :acting_as_shopify_organization
@@ -25,7 +25,6 @@ module ShopifyCli
25
25
  # ShopifyCli::Shopifolk.check
26
26
  #
27
27
  def check
28
- return false unless Feature.enabled?('shopifolk-beta')
29
28
  ShopifyCli::Shopifolk.new.shopifolk?
30
29
  end
31
30
 
@@ -34,7 +33,7 @@ module ShopifyCli
34
33
  end
35
34
 
36
35
  def acting_as_shopify_organization?
37
- !!@acting_as_shopify_organization || (Project.has_current? && Project.current.config['shopify_organization'])
36
+ !!@acting_as_shopify_organization || (Project.has_current? && Project.current.config["shopify_organization"])
38
37
  end
39
38
 
40
39
  def reset
@@ -51,7 +50,6 @@ module ShopifyCli
51
50
  # a valid google cloud config file with email ending in "@shopify.com"
52
51
  #
53
52
  def shopifolk?
54
- return false unless Feature.enabled?('shopifolk-beta')
55
53
  return true if Feature.enabled?(FEATURE_NAME)
56
54
 
57
55
  if shopifolk_by_gcloud? && shopifolk_by_dev?
@@ -66,7 +64,7 @@ module ShopifyCli
66
64
  private
67
65
 
68
66
  def shopifolk_by_gcloud?
69
- ini&.dig("[#{SECTION}]", 'account')&.match?(/@shopify.com\z/)
67
+ ini&.dig("[#{SECTION}]", "account")&.match?(/@shopify.com\z/)
70
68
  end
71
69
 
72
70
  def shopifolk_by_dev?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- require 'shopify_cli'
2
+ require "shopify_cli"
3
3
 
4
4
  module ShopifyCli
5
5
  class SubCommand < Command
@@ -1,4 +1,4 @@
1
- require 'shopify_cli'
1
+ require "shopify_cli"
2
2
 
3
3
  module ShopifyCli
4
4
  class Task
@@ -10,8 +10,8 @@ module ShopifyCli
10
10
  private
11
11
 
12
12
  def wants_to_run_against_shopify_org?
13
- @ctx.puts(@ctx.message('core.tasks.select_org_and_shop.identified_as_shopify'))
14
- message = @ctx.message('core.tasks.select_org_and_shop.first_party')
13
+ @ctx.puts(@ctx.message("core.tasks.select_org_and_shop.identified_as_shopify"))
14
+ message = @ctx.message("core.tasks.select_org_and_shop.first_party")
15
15
  CLI::UI::Prompt.confirm(message, default: false)
16
16
  end
17
17
  end
@@ -1,4 +1,4 @@
1
- require 'shopify_cli'
1
+ require "shopify_cli"
2
2
 
3
3
  module ShopifyCli
4
4
  module Tasks
@@ -30,11 +30,11 @@ module ShopifyCli
30
30
  Registry.add(-> () { const_get(task) }, name)
31
31
  end
32
32
 
33
- register :CreateApiClient, :create_api_client, 'shopify-cli/tasks/create_api_client'
34
- register :EnsureEnv, :ensure_env, 'shopify-cli/tasks/ensure_env'
35
- register :EnsureLoopbackURL, :ensure_loopback_url, 'shopify-cli/tasks/ensure_loopback_url'
36
- register :EnsureDevStore, :ensure_dev_store, 'shopify-cli/tasks/ensure_dev_store'
37
- register :SelectOrgAndShop, :select_org_and_shop, 'shopify-cli/tasks/select_org_and_shop'
38
- register :UpdateDashboardURLS, :update_dashboard_urls, 'shopify-cli/tasks/update_dashboard_urls'
33
+ register :CreateApiClient, :create_api_client, "shopify-cli/tasks/create_api_client"
34
+ register :EnsureEnv, :ensure_env, "shopify-cli/tasks/ensure_env"
35
+ register :EnsureLoopbackURL, :ensure_loopback_url, "shopify-cli/tasks/ensure_loopback_url"
36
+ register :EnsureDevStore, :ensure_dev_store, "shopify-cli/tasks/ensure_dev_store"
37
+ register :SelectOrgAndShop, :select_org_and_shop, "shopify-cli/tasks/select_org_and_shop"
38
+ register :UpdateDashboardURLS, :update_dashboard_urls, "shopify-cli/tasks/update_dashboard_urls"
39
39
  end
40
40
  end
@@ -1,15 +1,15 @@
1
- require 'shopify_cli'
1
+ require "shopify_cli"
2
2
 
3
3
  module ShopifyCli
4
4
  module Tasks
5
5
  class CreateApiClient < ShopifyCli::Task
6
6
  VALID_APP_TYPES = %w(public custom)
7
- DEFAULT_APP_URL = 'https://shopify.github.io/shopify-app-cli/help/start-app/'
7
+ DEFAULT_APP_URL = "https://shopify.github.io/shopify-app-cli/help/start-app/"
8
8
 
9
9
  def call(ctx, org_id:, title:, type:)
10
10
  resp = ShopifyCli::PartnersAPI.query(
11
11
  ctx,
12
- 'create_app',
12
+ "create_app",
13
13
  org: org_id.to_i,
14
14
  title: title,
15
15
  type: type,
@@ -23,12 +23,12 @@ module ShopifyCli
23
23
 
24
24
  errors = resp.dig("errors")
25
25
  if !errors.nil? && errors.any?
26
- ctx.abort(errors.map { |err| "#{err['field']} #{err['message']}" }.join(", "))
26
+ ctx.abort(errors.map { |err| "#{err["field"]} #{err["message"]}" }.join(", "))
27
27
  end
28
28
 
29
29
  user_errors = resp.dig("data", "appCreate", "userErrors")
30
30
  if !user_errors.nil? && user_errors.any?
31
- ctx.abort(user_errors.map { |err| "#{err['field']} #{err['message']}" }.join(", "))
31
+ ctx.abort(user_errors.map { |err| "#{err["field"]} #{err["message"]}" }.join(", "))
32
32
  end
33
33
 
34
34
  ShopifyCli::Core::Monorail.metadata[:api_key] = resp.dig("data", "appCreate", "app", "apiKey")
@@ -1,22 +1,22 @@
1
- require 'shopify_cli'
1
+ require "shopify_cli"
2
2
 
3
3
  module ShopifyCli
4
4
  module Tasks
5
5
  class EnsureDevStore < ShopifyCli::Task
6
6
  def call(ctx)
7
7
  @ctx = ctx
8
- return ctx.puts(ctx.message(
9
- 'core.tasks.ensure_dev_store.could_not_verify_store', project.env.shop
8
+ return ctx.abort(ctx.message(
9
+ "core.tasks.ensure_dev_store.could_not_verify_store", project.env.shop
10
10
  )) if shop.nil?
11
- return if shop['transferDisabled'] == true
11
+ return if shop["transferDisabled"] == true
12
12
  return unless CLI::UI::Prompt.confirm(
13
- ctx.message('core.tasks.ensure_dev_store.convert_to_dev_store', project.env.shop)
13
+ ctx.message("core.tasks.ensure_dev_store.convert_to_dev_store", project.env.shop)
14
14
  )
15
- ShopifyCli::PartnersAPI.query(ctx, 'convert_dev_to_test_store', input: {
16
- organizationID: shop['orgID'].to_i,
17
- shopId: shop['shopId'],
15
+ ShopifyCli::PartnersAPI.query(ctx, "convert_dev_to_test_store", input: {
16
+ organizationID: shop["orgID"].to_i,
17
+ shopId: shop["shopId"],
18
18
  })
19
- ctx.puts(ctx.message('core.tasks.ensure_dev_store.transfer_disabled', project.env.shop))
19
+ ctx.puts(ctx.message("core.tasks.ensure_dev_store.transfer_disabled", project.env.shop))
20
20
  end
21
21
 
22
22
  private
@@ -29,9 +29,9 @@ module ShopifyCli
29
29
  @shop ||= begin
30
30
  current_domain = project.env.shop
31
31
  ShopifyCli::PartnersAPI::Organizations.fetch_all(@ctx).map do |org|
32
- org['stores'].find do |store|
33
- store['orgID'] = org['id']
34
- store['shopDomain'] == current_domain
32
+ org["stores"].find do |store|
33
+ store["orgID"] = org["id"]
34
+ store["shopDomain"] == current_domain
35
35
  end
36
36
  end.compact.first
37
37
  end
@@ -1,4 +1,4 @@
1
- require 'shopify_cli'
1
+ require "shopify_cli"
2
2
 
3
3
  module ShopifyCli
4
4
  module Tasks
@@ -29,10 +29,10 @@ module ShopifyCli
29
29
  org_id = if orgs.count == 1
30
30
  orgs.first["id"]
31
31
  else
32
- CLI::UI::Prompt.ask(@ctx.message('core.tasks.ensure_env.organization_select')) do |handler|
32
+ CLI::UI::Prompt.ask(@ctx.message("core.tasks.ensure_env.organization_select")) do |handler|
33
33
  orgs.each do |org|
34
34
  handler.option(
35
- @ctx.message('core.partners_api.org_name_and_id', org['businessName'], org['id'])
35
+ @ctx.message("core.partners_api.org_name_and_id", org["businessName"], org["id"])
36
36
  ) { org["id"] }
37
37
  end
38
38
  end
@@ -44,15 +44,15 @@ module ShopifyCli
44
44
  if apps.count == 1
45
45
  apps.first
46
46
  elsif apps.count == 0
47
- @ctx.puts(@ctx.message('core.tasks.ensure_env.no_apps'))
48
- title = CLI::UI::Prompt.ask(@ctx.message('core.tasks.ensure_env.app_name'))
49
- type = CLI::UI::Prompt.ask(@ctx.message('core.tasks.ensure_env.app_type.select')) do |handler|
50
- handler.option(@ctx.message('core.tasks.ensure_env.app_type.select_public')) { 'public' }
51
- handler.option(@ctx.message('core.tasks.ensure_env.app_type.select_custom')) { 'custom' }
47
+ @ctx.puts(@ctx.message("core.tasks.ensure_env.no_apps"))
48
+ title = CLI::UI::Prompt.ask(@ctx.message("core.tasks.ensure_env.app_name"))
49
+ type = CLI::UI::Prompt.ask(@ctx.message("core.tasks.ensure_env.app_type.select")) do |handler|
50
+ handler.option(@ctx.message("core.tasks.ensure_env.app_type.select_public")) { "public" }
51
+ handler.option(@ctx.message("core.tasks.ensure_env.app_type.select_custom")) { "custom" }
52
52
  end
53
53
  ShopifyCli::Tasks::CreateApiClient.call(@ctx, org_id: org_id, title: title, type: type)
54
54
  else
55
- CLI::UI::Prompt.ask(@ctx.message('core.tasks.ensure_env.app_select')) do |handler|
55
+ CLI::UI::Prompt.ask(@ctx.message("core.tasks.ensure_env.app_select")) do |handler|
56
56
  apps.each { |app| handler.option(app["title"]) { app } }
57
57
  end
58
58
  end
@@ -62,9 +62,9 @@ module ShopifyCli
62
62
  if shops.count == 1
63
63
  shop = shops.first["shopDomain"]
64
64
  elsif shops.count == 0
65
- @ctx.puts(@ctx.message('core.tasks.ensure_env.no_development_stores', id))
65
+ @ctx.puts(@ctx.message("core.tasks.ensure_env.no_development_stores", id))
66
66
  else
67
- shop = CLI::UI::Prompt.ask(@ctx.message('core.tasks.ensure_env.development_store_select')) do |handler|
67
+ shop = CLI::UI::Prompt.ask(@ctx.message("core.tasks.ensure_env.development_store_select")) do |handler|
68
68
  shops.each { |s| handler.option(s["shopName"]) { s["shopDomain"] } }
69
69
  end
70
70
  end
@@ -72,13 +72,13 @@ module ShopifyCli
72
72
  end
73
73
 
74
74
  def write_env(env_data, org)
75
- id = org['id']
76
- app = get_app(id, org['apps'])
75
+ id = org["id"]
76
+ app = get_app(id, org["apps"])
77
77
 
78
- env_data[:shop] = get_shop(org['stores'], id)
78
+ env_data[:shop] = get_shop(org["stores"], id)
79
79
  env_data[:api_key] = app["apiKey"]
80
80
  env_data[:secret] = app["apiSecretKeys"].first["secret"]
81
- env_data[:scopes] = 'write_products,write_customers,write_draft_orders' if env_data[:scopes].nil?
81
+ env_data[:scopes] = "write_products,write_customers,write_draft_orders" if env_data[:scopes].nil?
82
82
  env_data[:extra] = {} if env_data[:extra].nil?
83
83
 
84
84
  Resources::EnvFile.new(
@@ -4,13 +4,13 @@ module ShopifyCli
4
4
  def call(ctx)
5
5
  @ctx = ctx
6
6
  api_key = Project.current.env.api_key
7
- result = ShopifyCli::PartnersAPI.query(ctx, 'get_app_urls', apiKey: api_key)
7
+ result = ShopifyCli::PartnersAPI.query(ctx, "get_app_urls", apiKey: api_key)
8
8
  loopback = OAuth::REDIRECT_HOST
9
- app = result['data']['app']
10
- urls = app['redirectUrlWhitelist']
9
+ app = result["data"]["app"]
10
+ urls = app["redirectUrlWhitelist"]
11
11
  if urls.grep(/#{loopback}/).empty?
12
12
  with_loopback = urls.push(loopback)
13
- ShopifyCli::PartnersAPI.query(@ctx, 'update_dashboard_urls', input: {
13
+ ShopifyCli::PartnersAPI.query(@ctx, "update_dashboard_urls", input: {
14
14
  redirectUrlWhitelist: with_loopback, apiKey: api_key
15
15
  })
16
16
  end
@@ -1,4 +1,4 @@
1
- require 'shopify_cli'
1
+ require "shopify_cli"
2
2
 
3
3
  module ShopifyCli
4
4
  module Tasks
@@ -12,7 +12,9 @@ module ShopifyCli
12
12
  Shopifolk.act_as_shopify_organization
13
13
  end
14
14
  org = get_organization(organization_id)
15
- shop_domain ||= get_shop_domain(org)
15
+ unless Shopifolk.acting_as_shopify_organization?
16
+ shop_domain ||= get_shop_domain(org)
17
+ end
16
18
  ShopifyCli::Core::Monorail.metadata[:organization_id] = org["id"].to_i
17
19
  response(org["id"].to_i, shop_domain)
18
20
  end
@@ -20,10 +22,9 @@ module ShopifyCli
20
22
  private
21
23
 
22
24
  def response(organization_id, shop_domain)
23
- {
24
- organization_id: organization_id,
25
- shop_domain: shop_domain,
26
- }
25
+ result = { organization_id: organization_id }
26
+ result[:shop_domain] = shop_domain if shop_domain
27
+ result
27
28
  end
28
29
 
29
30
  def organizations
@@ -34,45 +35,45 @@ module ShopifyCli
34
35
  @organization ||= if !organization_id.nil?
35
36
  org = ShopifyCli::PartnersAPI::Organizations.fetch(ctx, id: organization_id)
36
37
  if org.nil?
37
- ctx.puts(ctx.message('core.tasks.select_org_and_shop.error.authentication_issue', ShopifyCli::TOOL_NAME))
38
- ctx.abort(ctx.message('core.tasks.select_org_and_shop.error.organization_not_found'))
38
+ ctx.puts(ctx.message("core.tasks.select_org_and_shop.error.authentication_issue", ShopifyCli::TOOL_NAME))
39
+ ctx.abort(ctx.message("core.tasks.select_org_and_shop.error.organization_not_found"))
39
40
  end
40
41
  org
41
42
  elsif organizations.count == 0
42
- ctx.puts(ctx.message('core.tasks.select_org_and_shop.error.partners_notice'))
43
- ctx.puts(ctx.message('core.tasks.select_org_and_shop.authentication_issue', ShopifyCli::TOOL_NAME))
44
- ctx.abort(ctx.message('core.tasks.select_org_and_shop.error.no_organizations'))
43
+ ctx.puts(ctx.message("core.tasks.select_org_and_shop.error.partners_notice"))
44
+ ctx.puts(ctx.message("core.tasks.select_org_and_shop.authentication_issue", ShopifyCli::TOOL_NAME))
45
+ ctx.abort(ctx.message("core.tasks.select_org_and_shop.error.no_organizations"))
45
46
  elsif organizations.count == 1
46
47
  org = organizations.first
47
- ctx.puts(ctx.message('core.tasks.select_org_and_shop.organization', org['businessName'], org['id']))
48
+ ctx.puts(ctx.message("core.tasks.select_org_and_shop.organization", org["businessName"], org["id"]))
48
49
  org
49
50
  else
50
- org_id = CLI::UI::Prompt.ask(ctx.message('core.tasks.select_org_and_shop.organization_select')) do |handler|
51
+ org_id = CLI::UI::Prompt.ask(ctx.message("core.tasks.select_org_and_shop.organization_select")) do |handler|
51
52
  organizations.each do |o|
52
- handler.option(ctx.message('core.partners_api.org_name_and_id', o['businessName'], o['id'])) { o['id'] }
53
+ handler.option(ctx.message("core.partners_api.org_name_and_id", o["businessName"], o["id"])) { o["id"] }
53
54
  end
54
55
  end
55
- organizations.find { |o| o['id'] == org_id }
56
+ organizations.find { |o| o["id"] == org_id }
56
57
  end
57
58
  end
58
59
 
59
60
  def get_shop_domain(organization)
60
- valid_stores = organization['stores'].select do |store|
61
- store['transferDisabled'] == true || store['convertableToPartnerTest'] == true
61
+ valid_stores = organization["stores"].select do |store|
62
+ store["transferDisabled"] == true || store["convertableToPartnerTest"] == true
62
63
  end
63
64
 
64
65
  if valid_stores.count == 0
65
- ctx.puts(ctx.message('core.tasks.select_org_and_shop.error.no_development_stores'))
66
- ctx.puts(ctx.message('core.tasks.select_org_and_shop.create_store', organization['id']))
67
- ctx.puts(ctx.message('core.tasks.select_org_and_shop.authentication_issue', ShopifyCli::TOOL_NAME))
66
+ ctx.puts(ctx.message("core.tasks.select_org_and_shop.error.no_development_stores"))
67
+ ctx.puts(ctx.message("core.tasks.select_org_and_shop.create_store", organization["id"]))
68
+ ctx.puts(ctx.message("core.tasks.select_org_and_shop.authentication_issue", ShopifyCli::TOOL_NAME))
68
69
  elsif valid_stores.count == 1
69
- domain = valid_stores.first['shopDomain']
70
- ctx.puts(ctx.message('core.tasks.select_org_and_shop.development_store', domain))
70
+ domain = valid_stores.first["shopDomain"]
71
+ ctx.puts(ctx.message("core.tasks.select_org_and_shop.development_store", domain))
71
72
  domain
72
73
  else
73
74
  CLI::UI::Prompt.ask(
74
- ctx.message('core.tasks.select_org_and_shop.development_store_select'),
75
- options: valid_stores.map { |s| s['shopDomain'] }
75
+ ctx.message("core.tasks.select_org_and_shop.development_store_select"),
76
+ options: valid_stores.map { |s| s["shopDomain"] }
76
77
  )
77
78
  end
78
79
  end
@@ -7,24 +7,24 @@ module ShopifyCli
7
7
  @ctx = ctx
8
8
  project = ShopifyCli::Project.current
9
9
  api_key = project.env.api_key
10
- result = ShopifyCli::PartnersAPI.query(ctx, 'get_app_urls', apiKey: api_key)
11
- app = result['data']['app']
12
- consent = check_application_url(app['applicationUrl'], url)
13
- constructed_urls = construct_redirect_urls(app['redirectUrlWhitelist'], url, callback_url)
14
- return if url == app['applicationUrl']
15
- ShopifyCli::PartnersAPI.query(@ctx, 'update_dashboard_urls', input: {
16
- applicationUrl: consent ? url : app['applicationUrl'],
10
+ result = ShopifyCli::PartnersAPI.query(ctx, "get_app_urls", apiKey: api_key)
11
+ app = result["data"]["app"]
12
+ consent = check_application_url(app["applicationUrl"], url)
13
+ constructed_urls = construct_redirect_urls(app["redirectUrlWhitelist"], url, callback_url)
14
+ return if url == app["applicationUrl"]
15
+ ShopifyCli::PartnersAPI.query(@ctx, "update_dashboard_urls", input: {
16
+ applicationUrl: consent ? url : app["applicationUrl"],
17
17
  redirectUrlWhitelist: constructed_urls, apiKey: api_key
18
18
  })
19
- @ctx.puts(@ctx.message('core.tasks.update_dashboard_urls.updated'))
19
+ @ctx.puts(@ctx.message("core.tasks.update_dashboard_urls.updated"))
20
20
  rescue
21
- @ctx.puts(@ctx.message('core.tasks.update_dashboard_urls.update_error', ShopifyCli::TOOL_NAME))
21
+ @ctx.puts(@ctx.message("core.tasks.update_dashboard_urls.update_error", ShopifyCli::TOOL_NAME))
22
22
  raise
23
23
  end
24
24
 
25
25
  def check_application_url(application_url, new_url)
26
26
  return false if application_url.match(new_url)
27
- CLI::UI::Prompt.confirm(@ctx.message('core.tasks.update_dashboard_urls.update_prompt'))
27
+ CLI::UI::Prompt.confirm(@ctx.message("core.tasks.update_dashboard_urls.update_prompt"))
28
28
  end
29
29
 
30
30
  def construct_redirect_urls(urls, new_url, callback_url)
@@ -0,0 +1,86 @@
1
+
2
+ module ShopifyCli
3
+ ##
4
+ # `TransformDataStructure` helps to standardize data structure access. It
5
+ # traverses nested data structures and can convert
6
+ #
7
+ # * all strings used as keys to symbols,
8
+ # * all strings used as keys from `CamelCase` to `snake_case` and
9
+ # * associative array containers, e.g. from Hash to OpenStruct.
10
+ #
11
+ # Standardizing how a data structure is accessed greatly reduces the risk
12
+ # of subtle bugs especially when dealing with API responses.
13
+ #
14
+ # TransformDataStructure.new(
15
+ # symbolize_keys: true,
16
+ # underscore_keys: true,
17
+ # associative_array_container: OpenStruct
18
+ # ).call([{"SomeKey" => "value"}]).tap do |result|
19
+ # result.value # => [#<OpenStruct: some_key: "value">]
20
+ # end
21
+ #
22
+ # Since `TransformDataStructure` is a method object, it can easily be chained:
23
+ #
24
+ # require 'open-uri'
25
+ # ShopifyCli::Result
26
+ # .call { open("https://jsonplaceholder.typicode.com/todos/1") }
27
+ # .map(&TransformDataStructure.new(symbolize_keys: true, underscore_keys: true))
28
+ # .value # => { id: 1, user_id: 1, ... }
29
+ #
30
+ class TransformDataStructure
31
+ include ShopifyCli::MethodObject
32
+
33
+ class << self
34
+ private
35
+
36
+ def valid_associative_array_container(klass)
37
+ klass.respond_to?(:new) && klass.method_defined?(:[]=)
38
+ end
39
+ end
40
+
41
+ property! :underscore_keys, accepts: [true, false], default: false, reader: :underscore_keys?
42
+ property! :symbolize_keys, accepts: [true, false], default: false, reader: :symbolize_keys?
43
+ property! :associative_array_container,
44
+ accepts: ->(c) { c.respond_to?(:new) && c.method_defined?(:[]=) },
45
+ default: Hash
46
+
47
+ def call(object)
48
+ case object
49
+ when Array
50
+ object.map(&self).map(&:value)
51
+ when Hash
52
+ object.each.with_object(associative_array_container.new) do |(key, value), result|
53
+ result[transform_key(key)] = call(value).value
54
+ end
55
+ else
56
+ ShopifyCli::Result.success(object)
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def transform_key(key)
63
+ key
64
+ .yield_self(&method(:underscore_key))
65
+ .yield_self(&method(:symbolize_key))
66
+ end
67
+
68
+ def underscore_key(key)
69
+ return key unless underscore_keys? && key.respond_to?(:to_str)
70
+
71
+ key.to_str.dup.tap do |k|
72
+ k.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
73
+ k.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
74
+ k.tr!("-", "_")
75
+ k.gsub!(/\s/, "_")
76
+ k.gsub!(/__+/, "_")
77
+ k.downcase!
78
+ end
79
+ end
80
+
81
+ def symbolize_key(key)
82
+ return key unless symbolize_keys? && key.respond_to?(:to_sym)
83
+ key.to_sym
84
+ end
85
+ end
86
+ end