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,32 @@
1
+ module ShopifyCli
2
+ class PartnersAPI
3
+ class Organizations
4
+ class << self
5
+ def fetch_all(ctx)
6
+ resp = PartnersAPI.query(ctx, 'all_organizations')
7
+ resp['data']['organizations']['nodes'].map do |org|
8
+ org['stores'] = org['stores']['nodes']
9
+ org
10
+ end
11
+ end
12
+
13
+ def fetch(ctx, id:)
14
+ resp = PartnersAPI.query(ctx, 'find_organization', id: id)
15
+ org = resp['data']['organizations']['nodes'].first
16
+ return nil if org.nil?
17
+ org['stores'] = org['stores']['nodes']
18
+ org
19
+ end
20
+
21
+ def fetch_with_app(ctx)
22
+ resp = PartnersAPI.query(ctx, 'all_orgs_with_apps')
23
+ resp['data']['organizations']['nodes'].map do |org|
24
+ org['stores'] = org['stores']['nodes']
25
+ org['apps'] = org['apps']['nodes']
26
+ org
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,187 @@
1
+ require 'fileutils'
2
+
3
+ module ShopifyCli
4
+ ##
5
+ # ProcessSupervision wraps a running process spawned by `exec` and keeps track
6
+ # if its `pid` and keeps a log file for it as well
7
+ class ProcessSupervision
8
+ # is the directory where the pid and logfile are kept
9
+ RUN_DIR = File.join(ShopifyCli::CACHE_DIR, 'sv')
10
+
11
+ # a string or a symbol to identify this process by
12
+ attr_reader :identifier
13
+ # process ID for the running process
14
+ attr_reader :pid
15
+ # starttime of the process
16
+ attr_reader :time
17
+ # filepath to the pidfile for this process
18
+ attr_reader :pid_path
19
+ # filepath to the logfile for this process
20
+ attr_reader :log_path
21
+
22
+ class << self
23
+ ##
24
+ # Will find and create a new instance of ProcessSupervision for a running process
25
+ # if it is currently running. It will return nil if the process is not running.
26
+ #
27
+ # #### Parameters
28
+ #
29
+ # * `identifier` - a string or a symbol that a process was started with
30
+ #
31
+ # #### Returns
32
+ #
33
+ # * `process` - ProcessSupervision instance if the process is running this
34
+ # will be nil if the process is not running.
35
+ #
36
+ def for_ident(identifier)
37
+ pid, time = File.read(File.join(RUN_DIR, "#{identifier}.pid")).split(':')
38
+ new(identifier, pid: Integer(pid), time: time)
39
+ rescue Errno::ENOENT
40
+ nil
41
+ end
42
+
43
+ ##
44
+ # will fork and spawn a new process that is separate from the current process.
45
+ # This process will keep running beyond the command running so be careful!
46
+ #
47
+ # #### Parameters
48
+ #
49
+ # * `identifier` - a string or symbol to identify the new process by.
50
+ # * `args` - a command to run, either a string or array of strings
51
+ #
52
+ # #### Returns
53
+ #
54
+ # * `process` - ProcessSupervision instance if the process is running, this
55
+ # will be nil if the process did not start.
56
+ #
57
+ def start(identifier, args)
58
+ return for_ident(identifier) if running?(identifier)
59
+ fork do
60
+ pid_file = new(identifier, pid: Process.pid)
61
+ pid_file.write
62
+ STDOUT.reopen(pid_file.log_path, "w")
63
+ STDERR.reopen(pid_file.log_path, "w")
64
+ STDIN.reopen("/dev/null", "r")
65
+ Process.setsid
66
+ exec(*args)
67
+ end
68
+ sleep(0.1)
69
+ for_ident(identifier)
70
+ end
71
+
72
+ ##
73
+ # will attempt to shutdown a running process
74
+ #
75
+ # #### Parameters
76
+ #
77
+ # * `identifier` - a string or symbol to identify the new process by.
78
+ #
79
+ # #### Returns
80
+ #
81
+ # * `stopped` - [true, false]
82
+ #
83
+ def stop(identifier)
84
+ process = for_ident(identifier)
85
+ return false unless process
86
+ process.stop
87
+ end
88
+
89
+ ##
90
+ # will help identify if your process is still running in the background.
91
+ #
92
+ # #### Parameters
93
+ #
94
+ # * `identifier` - a string or symbol to identify the new process by.
95
+ #
96
+ # #### Returns
97
+ #
98
+ # * `running` - [true, false]
99
+ #
100
+ def running?(identifier)
101
+ process = for_ident(identifier)
102
+ return false unless process
103
+ process.alive?
104
+ end
105
+ end
106
+
107
+ def initialize(identifier, pid:, time: Time.now.strftime('%s')) # :nodoc:
108
+ @identifier = identifier
109
+ @pid = pid
110
+ @time = time
111
+ @pid_path = File.join(RUN_DIR, "#{identifier}.pid")
112
+ @log_path = File.join(RUN_DIR, "#{identifier}.log")
113
+ end
114
+
115
+ ##
116
+ # will attempt to shutdown a running process
117
+ #
118
+ # #### Returns
119
+ #
120
+ # * `stopped` - [true, false]
121
+ #
122
+ def stop
123
+ unlink
124
+ kill_proc
125
+ true
126
+ rescue
127
+ false
128
+ end
129
+
130
+ ##
131
+ # will help identify if your process is still running in the background.
132
+ #
133
+ # #### Returns
134
+ #
135
+ # * `alive` - [true, false]
136
+ #
137
+ def alive?
138
+ stat(pid)
139
+ end
140
+
141
+ ##
142
+ # persists the pidfile
143
+ #
144
+ def write
145
+ FileUtils.mkdir_p(File.dirname(pid_path))
146
+ File.write(pid_path, "#{pid}:#{time}")
147
+ end
148
+
149
+ private
150
+
151
+ def unlink
152
+ File.unlink(pid_path)
153
+ File.unlink(log_path)
154
+ nil
155
+ rescue Errno::ENOENT
156
+ nil
157
+ end
158
+
159
+ def kill_proc
160
+ kill(-pid) # process group
161
+ rescue Errno::ESRCH
162
+ begin
163
+ kill(pid)
164
+ rescue Errno::ESRCH # The process group does not exist, try the pid itself
165
+ # Race condition, process died in the middle
166
+ end
167
+ end
168
+
169
+ def kill(id)
170
+ Process.kill('TERM', id)
171
+ 50.times do
172
+ sleep 0.1
173
+ break unless stat(id)
174
+ end
175
+ Process.kill('KILL', id) if stat(id)
176
+ end
177
+
178
+ def stat(id)
179
+ Process.kill(0, id) # signal 0 checks if pid is alive
180
+ true
181
+ rescue Errno::EPERM
182
+ true
183
+ rescue Errno::ESRCH
184
+ false
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,191 @@
1
+ # frozen_string_literal: true
2
+ require 'shopify_cli'
3
+
4
+ module ShopifyCli
5
+ ##
6
+ # ShopifyCli::Project captures the current project that the user is working on.
7
+ # This class can be used to fetch and save project environment as well as the
8
+ # project config `.shopify-cli.yml`.
9
+ #
10
+ class Project
11
+ include SmartProperties
12
+
13
+ class << self
14
+ ##
15
+ # will get an instance of the project that the user is currently operating
16
+ # on. This is used for access to project resources.
17
+ #
18
+ # #### Returns
19
+ #
20
+ # * `project` - a Project instance if the user is currently in the project.
21
+ #
22
+ # #### Raises
23
+ #
24
+ # * `ShopifyCli::Abort` - If the cli is not currently in a project directory
25
+ # then this will be raised with a message implying that the user is not in
26
+ # a project directory.
27
+ #
28
+ # #### Example
29
+ #
30
+ # project = ShopifyCli::Project.current
31
+ #
32
+ def current
33
+ at(Dir.pwd)
34
+ end
35
+
36
+ ##
37
+ # will return true if the command line is currently within a project
38
+ #
39
+ # #### Returns
40
+ #
41
+ # * `has_current?` - boolean, true if there is a current project
42
+ #
43
+ def has_current?
44
+ !directory(Dir.pwd).nil?
45
+ end
46
+
47
+ ##
48
+ # will fetch the project type of the current project. This is mostly used
49
+ # for internal project type loading, you should not normally need this.
50
+ #
51
+ # #### Returns
52
+ #
53
+ # * `type` - a symbol of the name of the project type identifier. i.e. [rails, node]
54
+ # This will be nil if the user is not in a current project.
55
+ #
56
+ # #### Example
57
+ #
58
+ # type = ShopifyCli::Project.current_project_type
59
+ #
60
+ def current_project_type
61
+ return unless has_current?
62
+ current.config['project_type'].to_sym
63
+ end
64
+
65
+ ##
66
+ # writes out the `.shopify-cli.yml` file. You should use this when creating
67
+ # a project type so that the rest of your project type commands will load
68
+ # in this project, in the future.
69
+ #
70
+ # #### Parameters
71
+ #
72
+ # * `ctx` - the current running context of your command
73
+ # * `project_type` - a string or symbol of your project type name
74
+ # * `organization_id` - the id of the partner organization that the app is owned by. Used for metrics
75
+ # * `identifiers` - an optional hash of other app identifiers
76
+ #
77
+ # #### Example
78
+ #
79
+ # type = ShopifyCli::Project.current_project_type
80
+ #
81
+ def write(ctx, project_type:, organization_id:, **identifiers)
82
+ require 'yaml' # takes 20ms, so deferred as late as possible.
83
+ content = Hash[{ project_type: project_type, organization_id: organization_id.to_i }
84
+ .merge(identifiers)
85
+ .collect { |k, v| [k.to_s, v] }]
86
+
87
+ ctx.write('.shopify-cli.yml', YAML.dump(content))
88
+ end
89
+
90
+ def project_name
91
+ File.basename(current.directory)
92
+ end
93
+
94
+ private
95
+
96
+ def directory(dir)
97
+ @dir ||= Hash.new { |h, k| h[k] = __directory(k) }
98
+ @dir[dir]
99
+ end
100
+
101
+ def at(dir)
102
+ proj_dir = directory(dir)
103
+ unless proj_dir
104
+ raise(ShopifyCli::Abort, Context.message('core.project.error.not_in_project'))
105
+ end
106
+ @at ||= Hash.new { |h, k| h[k] = new(directory: k) }
107
+ @at[proj_dir]
108
+ end
109
+
110
+ def __directory(curr)
111
+ loop do
112
+ return nil if curr == '/'
113
+ file = File.join(curr, '.shopify-cli.yml')
114
+ return curr if File.exist?(file)
115
+ curr = File.dirname(curr)
116
+ end
117
+ end
118
+ end
119
+
120
+ property :directory # :nodoc:
121
+
122
+ ##
123
+ # will read, parse and return the envfile for the project
124
+ #
125
+ # #### Returns
126
+ #
127
+ # * `env` - An instance of a ShopifyCli::Resources::EnvFile
128
+ #
129
+ # #### Example
130
+ #
131
+ # ShopifyCli::Project.current.env
132
+ #
133
+ def env
134
+ @env ||= begin
135
+ Resources::EnvFile.read(directory)
136
+ rescue Errno::ENOENT
137
+ nil
138
+ end
139
+ end
140
+
141
+ ##
142
+ # will read, parse and return the .shopify-cli.yml for the project
143
+ #
144
+ # #### Returns
145
+ #
146
+ # * `config` - A hash of configuration
147
+ #
148
+ # #### Raises
149
+ #
150
+ # * `ShopifyCli::Abort` - If the yml is invalid or poorly formatted
151
+ # * `ShopifyCli::Abort` - If the yml file does not exist
152
+ #
153
+ # #### Example
154
+ #
155
+ # ShopifyCli::Project.current.config
156
+ #
157
+ def config
158
+ @config ||= begin
159
+ config = load_yaml_file('.shopify-cli.yml')
160
+ unless config.is_a?(Hash)
161
+ raise ShopifyCli::Abort, Context.message('core.project.error.cli_yaml.not_hash')
162
+ end
163
+
164
+ # The app_type key was deprecated in favour of project_type, so replace it
165
+ if config.key?('app_type')
166
+ config['project_type'] = config['app_type']
167
+ config.delete('app_type')
168
+ end
169
+
170
+ config
171
+ end
172
+ end
173
+
174
+ private
175
+
176
+ def load_yaml_file(relative_path)
177
+ f = File.join(directory, relative_path)
178
+ require 'yaml' # takes 20ms, so deferred as late as possible.
179
+ begin
180
+ YAML.load_file(f)
181
+ rescue Psych::SyntaxError => e
182
+ raise(ShopifyCli::Abort, Context.message('core.project.error.cli_yaml.invalid', relative_path, e.message))
183
+ # rescue Errno::EACCES => e
184
+ # TODO
185
+ # Dev::Helpers::EaccesHandler.diagnose_and_raise(f, e, mode: :read)
186
+ rescue Errno::ENOENT
187
+ raise ShopifyCli::Abort, Context.message('core.project.error.cli_yaml.not_found', f)
188
+ end
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,83 @@
1
+ module ShopifyCli
2
+ class ProjectType
3
+ class << self
4
+ attr_accessor :project_type,
5
+ :project_name,
6
+ :project_creator_command_class,
7
+ :project_load_shallow
8
+ attr_reader :hidden
9
+
10
+ def repository
11
+ @repository ||= []
12
+ end
13
+ alias_method :all_loaded, :repository
14
+
15
+ def inherited(klass)
16
+ repository << klass
17
+ klass.project_type = @current_type
18
+ klass.project_load_shallow = @shallow_load
19
+ end
20
+
21
+ def load_type(current_type, shallow = false)
22
+ filepath = File.join(ShopifyCli::ROOT, 'lib', 'project_types', current_type.to_s, 'cli.rb')
23
+ return unless File.exist?(filepath)
24
+ @shallow_load = shallow
25
+ @current_type = current_type
26
+ load(filepath)
27
+ @current_type = nil
28
+ @shallow_load = false
29
+ for_app_type(current_type)
30
+ end
31
+
32
+ def load_all
33
+ Dir.glob(File.join(ShopifyCli::ROOT, 'lib', 'project_types', '*', 'cli.rb')).map do |filepath|
34
+ load_type(filepath.split(File::Separator)[-2], true)
35
+ end
36
+ end
37
+
38
+ def for_app_type(type)
39
+ repository.find { |k| k.project_type.to_s == type.to_s }
40
+ end
41
+
42
+ def project_filepath(path)
43
+ File.join(ShopifyCli::PROJECT_TYPES_DIR, project_type.to_s, path)
44
+ end
45
+
46
+ def creator(name, command_const)
47
+ @project_name = name
48
+ @project_creator_command_class = command_const
49
+ ShopifyCli::Commands::Create.subcommand(command_const, @project_type)
50
+ end
51
+
52
+ def create_command
53
+ const_get(@project_creator_command_class)
54
+ end
55
+
56
+ def hidden_project_type
57
+ @hidden = true
58
+ end
59
+
60
+ def register_command(const, cmd)
61
+ return if project_load_shallow
62
+ Context.new.abort(
63
+ Context.message('core.project_type.error.cannot_override_core', cmd, const)
64
+ ) if Commands.core_command?(cmd)
65
+ Commands.register(const, cmd)
66
+ end
67
+
68
+ def register_task(task, name)
69
+ return if project_load_shallow
70
+ Task::Registry.add(const_get(task), name)
71
+ end
72
+
73
+ def register_messages(messages)
74
+ # Make sure we don't attempt to register a file more than once as that will fail
75
+ @registered_message_files ||= {}
76
+ return if @registered_message_files.key?(@project_type)
77
+ @registered_message_files[@project_type] = true
78
+
79
+ Context.load_messages(messages)
80
+ end
81
+ end
82
+ end
83
+ end