shopify-cli 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (273) hide show
  1. checksums.yaml +7 -0
  2. data/.github/CODEOWNERS +1 -0
  3. data/.github/CODE_OF_CONDUCT.md +73 -0
  4. data/.github/CONTRIBUTING.md +51 -0
  5. data/.github/DESIGN.md +153 -0
  6. data/.github/ISSUE_TEMPLATE.md +38 -0
  7. data/.github/PULL_REQUEST_TEMPLATE.md +22 -0
  8. data/.github/probots.yml +3 -0
  9. data/.gitignore +19 -0
  10. data/.rubocop.yml +47 -0
  11. data/.ruby-version +1 -0
  12. data/.travis.yml +12 -0
  13. data/Gemfile +22 -0
  14. data/Gemfile.lock +77 -0
  15. data/LICENSE.md +7 -0
  16. data/README.md +13 -0
  17. data/Rakefile +101 -0
  18. data/SECURITY.md +59 -0
  19. data/Vagrantfile +17 -0
  20. data/bin/load_shopify.rb +20 -0
  21. data/bin/shopify +32 -0
  22. data/dev.yml +17 -0
  23. data/docs/Gemfile +5 -0
  24. data/docs/Gemfile.lock +248 -0
  25. data/docs/_config.yml +16 -0
  26. data/docs/_data/nav.yml +26 -0
  27. data/docs/_includes/footer.html +15 -0
  28. data/docs/_includes/head.html +19 -0
  29. data/docs/_includes/sidebar_nav.html +22 -0
  30. data/docs/_includes/toc.html +112 -0
  31. data/docs/_layouts/default.html +79 -0
  32. data/docs/app/node/commands/index.md +82 -0
  33. data/docs/app/node/index.md +35 -0
  34. data/docs/app/rails/commands/index.md +80 -0
  35. data/docs/app/rails/index.md +36 -0
  36. data/docs/core/index.md +70 -0
  37. data/docs/css/docs.css +157 -0
  38. data/docs/getting-started/index.md +61 -0
  39. data/docs/help/start-app/index.md +6 -0
  40. data/docs/images/header.png +0 -0
  41. data/docs/index.md +27 -0
  42. data/docs/installing-ruby.md +28 -0
  43. data/ext/shopify-cli/extconf.rb +27 -0
  44. data/install.sh +7 -0
  45. data/lib/docgen/class_template.md.erb +81 -0
  46. data/lib/docgen/index_template.md.erb +5 -0
  47. data/lib/docgen/markdown.rb +101 -0
  48. data/lib/graphql/admin_introspection.graphql +87 -0
  49. data/lib/graphql/all_organizations.graphql +19 -0
  50. data/lib/graphql/all_orgs_with_apps.graphql +30 -0
  51. data/lib/graphql/api_versions.graphql +6 -0
  52. data/lib/graphql/convert_dev_to_test_store.graphql +10 -0
  53. data/lib/graphql/create_app.graphql +20 -0
  54. data/lib/graphql/create_customer.graphql +9 -0
  55. data/lib/graphql/create_draft_order.graphql +8 -0
  56. data/lib/graphql/create_product.graphql +9 -0
  57. data/lib/graphql/extension_create.graphql +21 -0
  58. data/lib/graphql/extension_update_draft.graphql +18 -0
  59. data/lib/graphql/find_organization.graphql +17 -0
  60. data/lib/graphql/get_app_urls.graphql +6 -0
  61. data/lib/graphql/update_dashboard_urls.graphql +8 -0
  62. data/lib/project_types/extension/cli.rb +71 -0
  63. data/lib/project_types/extension/commands/build.rb +29 -0
  64. data/lib/project_types/extension/commands/create.rb +49 -0
  65. data/lib/project_types/extension/commands/extension_command.rb +22 -0
  66. data/lib/project_types/extension/commands/push.rb +69 -0
  67. data/lib/project_types/extension/commands/register.rb +78 -0
  68. data/lib/project_types/extension/commands/serve.rb +24 -0
  69. data/lib/project_types/extension/commands/tunnel.rb +69 -0
  70. data/lib/project_types/extension/extension_project.rb +85 -0
  71. data/lib/project_types/extension/extension_project_keys.rb +10 -0
  72. data/lib/project_types/extension/features/argo.rb +48 -0
  73. data/lib/project_types/extension/features/argo_dependencies.rb +28 -0
  74. data/lib/project_types/extension/features/argo_setup.rb +54 -0
  75. data/lib/project_types/extension/features/argo_setup_step.rb +31 -0
  76. data/lib/project_types/extension/features/argo_setup_steps.rb +53 -0
  77. data/lib/project_types/extension/features/tunnel_url.rb +20 -0
  78. data/lib/project_types/extension/forms/create.rb +52 -0
  79. data/lib/project_types/extension/forms/register.rb +48 -0
  80. data/lib/project_types/extension/messages/message_loading.rb +37 -0
  81. data/lib/project_types/extension/messages/messages.rb +126 -0
  82. data/lib/project_types/extension/models/app.rb +14 -0
  83. data/lib/project_types/extension/models/registration.rb +19 -0
  84. data/lib/project_types/extension/models/type.rb +76 -0
  85. data/lib/project_types/extension/models/types/checkout_post_purchase.rb +20 -0
  86. data/lib/project_types/extension/models/types/subscription_management.rb +20 -0
  87. data/lib/project_types/extension/models/validation_error.rb +17 -0
  88. data/lib/project_types/extension/models/version.rb +15 -0
  89. data/lib/project_types/extension/tasks/converters/registration_converter.rb +26 -0
  90. data/lib/project_types/extension/tasks/converters/validation_error_converter.rb +25 -0
  91. data/lib/project_types/extension/tasks/converters/version_converter.rb +28 -0
  92. data/lib/project_types/extension/tasks/create_extension.rb +31 -0
  93. data/lib/project_types/extension/tasks/get_apps.rb +34 -0
  94. data/lib/project_types/extension/tasks/update_draft.rb +29 -0
  95. data/lib/project_types/extension/tasks/user_errors.rb +45 -0
  96. data/lib/project_types/node/cli.rb +37 -0
  97. data/lib/project_types/node/commands/create.rb +117 -0
  98. data/lib/project_types/node/commands/deploy.rb +22 -0
  99. data/lib/project_types/node/commands/deploy/heroku.rb +91 -0
  100. data/lib/project_types/node/commands/generate.rb +51 -0
  101. data/lib/project_types/node/commands/generate/billing.rb +37 -0
  102. data/lib/project_types/node/commands/generate/page.rb +55 -0
  103. data/lib/project_types/node/commands/generate/webhook.rb +33 -0
  104. data/lib/project_types/node/commands/open.rb +16 -0
  105. data/lib/project_types/node/commands/populate.rb +23 -0
  106. data/lib/project_types/node/commands/populate/customer.rb +31 -0
  107. data/lib/project_types/node/commands/populate/draft_order.rb +28 -0
  108. data/lib/project_types/node/commands/populate/product.rb +30 -0
  109. data/lib/project_types/node/commands/serve.rb +45 -0
  110. data/lib/project_types/node/commands/tunnel.rb +39 -0
  111. data/lib/project_types/node/forms/create.rb +87 -0
  112. data/lib/project_types/node/messages/messages.rb +260 -0
  113. data/lib/project_types/rails/cli.rb +41 -0
  114. data/lib/project_types/rails/commands/create.rb +126 -0
  115. data/lib/project_types/rails/commands/deploy.rb +22 -0
  116. data/lib/project_types/rails/commands/deploy/heroku.rb +113 -0
  117. data/lib/project_types/rails/commands/generate.rb +49 -0
  118. data/lib/project_types/rails/commands/generate/webhook.rb +39 -0
  119. data/lib/project_types/rails/commands/open.rb +16 -0
  120. data/lib/project_types/rails/commands/populate.rb +23 -0
  121. data/lib/project_types/rails/commands/populate/customer.rb +31 -0
  122. data/lib/project_types/rails/commands/populate/draft_order.rb +28 -0
  123. data/lib/project_types/rails/commands/populate/product.rb +30 -0
  124. data/lib/project_types/rails/commands/serve.rb +47 -0
  125. data/lib/project_types/rails/commands/tunnel.rb +39 -0
  126. data/lib/project_types/rails/forms/create.rb +116 -0
  127. data/lib/project_types/rails/gem.rb +56 -0
  128. data/lib/project_types/rails/messages/messages.rb +283 -0
  129. data/lib/project_types/rails/ruby.rb +17 -0
  130. data/lib/project_types/script/cli.rb +76 -0
  131. data/lib/project_types/script/commands/create.rb +45 -0
  132. data/lib/project_types/script/commands/disable.rb +36 -0
  133. data/lib/project_types/script/commands/enable.rb +46 -0
  134. data/lib/project_types/script/commands/push.rb +39 -0
  135. data/lib/project_types/script/config/extension_points.yml +18 -0
  136. data/lib/project_types/script/errors.rb +16 -0
  137. data/lib/project_types/script/forms/create.rb +29 -0
  138. data/lib/project_types/script/forms/enable.rb +24 -0
  139. data/lib/project_types/script/forms/push.rb +19 -0
  140. data/lib/project_types/script/forms/script_form.rb +66 -0
  141. data/lib/project_types/script/graphql/app_script_update_or_create.graphql +27 -0
  142. data/lib/project_types/script/graphql/script_service_proxy.graphql +8 -0
  143. data/lib/project_types/script/graphql/shop_script_delete.graphql +14 -0
  144. data/lib/project_types/script/graphql/shop_script_update_or_create.graphql +28 -0
  145. data/lib/project_types/script/layers/application/build_script.rb +43 -0
  146. data/lib/project_types/script/layers/application/create_script.rb +47 -0
  147. data/lib/project_types/script/layers/application/disable_script.rb +19 -0
  148. data/lib/project_types/script/layers/application/enable_script.rb +21 -0
  149. data/lib/project_types/script/layers/application/extension_points.rb +17 -0
  150. data/lib/project_types/script/layers/application/project_dependencies.rb +34 -0
  151. data/lib/project_types/script/layers/application/push_script.rb +30 -0
  152. data/lib/project_types/script/layers/domain/errors.rb +25 -0
  153. data/lib/project_types/script/layers/domain/extension_point.rb +29 -0
  154. data/lib/project_types/script/layers/domain/push_package.rb +29 -0
  155. data/lib/project_types/script/layers/domain/script.rb +18 -0
  156. data/lib/project_types/script/layers/infrastructure/assemblyscript_dependency_manager.rb +73 -0
  157. data/lib/project_types/script/layers/infrastructure/assemblyscript_tsconfig.rb +38 -0
  158. data/lib/project_types/script/layers/infrastructure/assemblyscript_wasm_builder.rb +39 -0
  159. data/lib/project_types/script/layers/infrastructure/dependency_manager.rb +36 -0
  160. data/lib/project_types/script/layers/infrastructure/errors.rb +38 -0
  161. data/lib/project_types/script/layers/infrastructure/extension_point_repository.rb +31 -0
  162. data/lib/project_types/script/layers/infrastructure/push_package_repository.rb +47 -0
  163. data/lib/project_types/script/layers/infrastructure/script_builder.rb +34 -0
  164. data/lib/project_types/script/layers/infrastructure/script_repository.rb +89 -0
  165. data/lib/project_types/script/layers/infrastructure/script_service.rb +165 -0
  166. data/lib/project_types/script/layers/infrastructure/test_suite_repository.rb +59 -0
  167. data/lib/project_types/script/messages/messages.rb +204 -0
  168. data/lib/project_types/script/script_project.rb +37 -0
  169. data/lib/project_types/script/templates/ts/as-pect.config.js +21 -0
  170. data/lib/project_types/script/ui/error_handler.rb +136 -0
  171. data/lib/project_types/script/ui/strict_spinner.rb +22 -0
  172. data/lib/rubygems_plugin.rb +18 -0
  173. data/lib/shopify-cli/admin_api.rb +99 -0
  174. data/lib/shopify-cli/admin_api/populate_resource_command.rb +165 -0
  175. data/lib/shopify-cli/admin_api/schema.rb +32 -0
  176. data/lib/shopify-cli/api.rb +104 -0
  177. data/lib/shopify-cli/command.rb +67 -0
  178. data/lib/shopify-cli/commands.rb +28 -0
  179. data/lib/shopify-cli/commands/connect.rb +108 -0
  180. data/lib/shopify-cli/commands/create.rb +50 -0
  181. data/lib/shopify-cli/commands/help.rb +79 -0
  182. data/lib/shopify-cli/commands/logout.rb +23 -0
  183. data/lib/shopify-cli/commands/system.rb +135 -0
  184. data/lib/shopify-cli/commands/version.rb +15 -0
  185. data/lib/shopify-cli/context.rb +372 -0
  186. data/lib/shopify-cli/core.rb +9 -0
  187. data/lib/shopify-cli/core/entry_point.rb +40 -0
  188. data/lib/shopify-cli/core/executor.rb +21 -0
  189. data/lib/shopify-cli/core/help_resolver.rb +20 -0
  190. data/lib/shopify-cli/core/monorail.rb +118 -0
  191. data/lib/shopify-cli/db.rb +114 -0
  192. data/lib/shopify-cli/form.rb +40 -0
  193. data/lib/shopify-cli/git.rb +141 -0
  194. data/lib/shopify-cli/helpers.rb +5 -0
  195. data/lib/shopify-cli/helpers/haikunator.rb +92 -0
  196. data/lib/shopify-cli/heroku.rb +97 -0
  197. data/lib/shopify-cli/js_deps.rb +110 -0
  198. data/lib/shopify-cli/js_system.rb +98 -0
  199. data/lib/shopify-cli/messages/messages.rb +287 -0
  200. data/lib/shopify-cli/oauth.rb +192 -0
  201. data/lib/shopify-cli/oauth/servlet.rb +61 -0
  202. data/lib/shopify-cli/options.rb +40 -0
  203. data/lib/shopify-cli/packager.rb +116 -0
  204. data/lib/shopify-cli/partners_api.rb +114 -0
  205. data/lib/shopify-cli/partners_api/organizations.rb +32 -0
  206. data/lib/shopify-cli/process_supervision.rb +187 -0
  207. data/lib/shopify-cli/project.rb +191 -0
  208. data/lib/shopify-cli/project_type.rb +83 -0
  209. data/lib/shopify-cli/resources.rb +5 -0
  210. data/lib/shopify-cli/resources/env_file.rb +96 -0
  211. data/lib/shopify-cli/sub_command.rb +15 -0
  212. data/lib/shopify-cli/task.rb +10 -0
  213. data/lib/shopify-cli/tasks.rb +32 -0
  214. data/lib/shopify-cli/tasks/create_api_client.rb +29 -0
  215. data/lib/shopify-cli/tasks/ensure_dev_store.rb +41 -0
  216. data/lib/shopify-cli/tasks/ensure_env.rb +31 -0
  217. data/lib/shopify-cli/tasks/ensure_loopback_url.rb +20 -0
  218. data/lib/shopify-cli/tasks/update_dashboard_urls.rb +44 -0
  219. data/lib/shopify-cli/tunnel.rb +154 -0
  220. data/lib/shopify-cli/version.rb +3 -0
  221. data/lib/shopify_cli.rb +132 -0
  222. data/shopify-cli.gemspec +40 -0
  223. data/shopify.fish +12 -0
  224. data/shopify.sh +11 -0
  225. data/vendor/deps/cli-kit/REVISION +1 -0
  226. data/vendor/deps/cli-kit/lib/cli/kit.rb +60 -0
  227. data/vendor/deps/cli-kit/lib/cli/kit/autocall.rb +21 -0
  228. data/vendor/deps/cli-kit/lib/cli/kit/base_command.rb +49 -0
  229. data/vendor/deps/cli-kit/lib/cli/kit/command_registry.rb +94 -0
  230. data/vendor/deps/cli-kit/lib/cli/kit/config.rb +133 -0
  231. data/vendor/deps/cli-kit/lib/cli/kit/error_handler.rb +115 -0
  232. data/vendor/deps/cli-kit/lib/cli/kit/executor.rb +81 -0
  233. data/vendor/deps/cli-kit/lib/cli/kit/ini.rb +102 -0
  234. data/vendor/deps/cli-kit/lib/cli/kit/levenshtein.rb +82 -0
  235. data/vendor/deps/cli-kit/lib/cli/kit/logger.rb +76 -0
  236. data/vendor/deps/cli-kit/lib/cli/kit/resolver.rb +60 -0
  237. data/vendor/deps/cli-kit/lib/cli/kit/ruby_backports/enumerable.rb +6 -0
  238. data/vendor/deps/cli-kit/lib/cli/kit/support.rb +9 -0
  239. data/vendor/deps/cli-kit/lib/cli/kit/support/test_helper.rb +244 -0
  240. data/vendor/deps/cli-kit/lib/cli/kit/system.rb +207 -0
  241. data/vendor/deps/cli-kit/lib/cli/kit/util.rb +189 -0
  242. data/vendor/deps/cli-kit/lib/cli/kit/version.rb +5 -0
  243. data/vendor/deps/cli-ui/REVISION +1 -0
  244. data/vendor/deps/cli-ui/lib/cli/ui.rb +187 -0
  245. data/vendor/deps/cli-ui/lib/cli/ui/ansi.rb +153 -0
  246. data/vendor/deps/cli-ui/lib/cli/ui/box.rb +15 -0
  247. data/vendor/deps/cli-ui/lib/cli/ui/color.rb +79 -0
  248. data/vendor/deps/cli-ui/lib/cli/ui/formatter.rb +179 -0
  249. data/vendor/deps/cli-ui/lib/cli/ui/frame.rb +310 -0
  250. data/vendor/deps/cli-ui/lib/cli/ui/glyph.rb +78 -0
  251. data/vendor/deps/cli-ui/lib/cli/ui/progress.rb +88 -0
  252. data/vendor/deps/cli-ui/lib/cli/ui/prompt.rb +248 -0
  253. data/vendor/deps/cli-ui/lib/cli/ui/prompt/interactive_options.rb +472 -0
  254. data/vendor/deps/cli-ui/lib/cli/ui/prompt/options_handler.rb +24 -0
  255. data/vendor/deps/cli-ui/lib/cli/ui/spinner.rb +48 -0
  256. data/vendor/deps/cli-ui/lib/cli/ui/spinner/async.rb +40 -0
  257. data/vendor/deps/cli-ui/lib/cli/ui/spinner/spin_group.rb +241 -0
  258. data/vendor/deps/cli-ui/lib/cli/ui/stdout_router.rb +227 -0
  259. data/vendor/deps/cli-ui/lib/cli/ui/terminal.rb +36 -0
  260. data/vendor/deps/cli-ui/lib/cli/ui/truncater.rb +102 -0
  261. data/vendor/deps/cli-ui/lib/cli/ui/version.rb +5 -0
  262. data/vendor/deps/smart_properties/REVISION +1 -0
  263. data/vendor/deps/smart_properties/lib/smart_properties.rb +174 -0
  264. data/vendor/deps/smart_properties/lib/smart_properties/errors.rb +114 -0
  265. data/vendor/deps/smart_properties/lib/smart_properties/property.rb +162 -0
  266. data/vendor/deps/smart_properties/lib/smart_properties/property_collection.rb +83 -0
  267. data/vendor/deps/smart_properties/lib/smart_properties/validations.rb +8 -0
  268. data/vendor/deps/smart_properties/lib/smart_properties/validations/ancestor.rb +27 -0
  269. data/vendor/deps/smart_properties/lib/smart_properties/version.rb +3 -0
  270. data/vendor/lib/semantic/LICENSE +20 -0
  271. data/vendor/lib/semantic/semantic.rb +4 -0
  272. data/vendor/lib/semantic/version.rb +180 -0
  273. metadata +374 -0
@@ -0,0 +1,189 @@
1
+ module CLI
2
+ module Kit
3
+ module Util
4
+ class << self
5
+ def snake_case(camel_case, seperator = "_")
6
+ camel_case.to_s # MyCoolThing::MyAPIModule
7
+ .gsub(/::/, '/') # MyCoolThing/MyAPIModule
8
+ .gsub(/([A-Z]+)([A-Z][a-z])/, "\\1#{seperator}\\2") # MyCoolThing::MyAPI_Module
9
+ .gsub(/([a-z\d])([A-Z])/, "\\1#{seperator}\\2") # My_Cool_Thing::My_API_Module
10
+ .downcase # my_cool_thing/my_api_module
11
+ end
12
+
13
+ def dash_case(camel_case)
14
+ snake_case(camel_case, '-')
15
+ end
16
+
17
+ # The following methods is taken from activesupport
18
+ # All credit for this method goes to the original authors.
19
+ # https://github.com/rails/rails/blob/d66e7835bea9505f7003e5038aa19b6ea95ceea1/activesupport/lib/active_support/core_ext/string/strip.rb
20
+ #
21
+ # Copyright (c) 2005-2018 David Heinemeier Hansson
22
+ #
23
+ # Permission is hereby granted, free of charge, to any person obtaining
24
+ # a copy of this software and associated documentation files (the
25
+ # "Software"), to deal in the Software without restriction, including
26
+ # without limitation the rights to use, copy, modify, merge, publish,
27
+ # distribute, sublicense, and/or sell copies of the Software, and to
28
+ # permit persons to whom the Software is furnished to do so, subject to
29
+ # the following conditions:
30
+ #
31
+ # The above copyright notice and this permission notice shall be
32
+ # included in all copies or substantial portions of the Software.
33
+ #
34
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
35
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
36
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
37
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
38
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
39
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
40
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
41
+ #
42
+ # Strips indentation by removing the amount of leading whitespace in the least indented
43
+ # non-empty line in the whole string
44
+ #
45
+ def strip_heredoc(str)
46
+ str.gsub(/^#{str.scan(/^[ \t]*(?=\S)/).min}/, "".freeze)
47
+ end
48
+
49
+ # Joins an array with commas and "and", using the Oxford comma.
50
+ def english_join(array)
51
+ return "" if array.nil?
52
+ return array.join(" and ") if array.length < 3
53
+
54
+ "#{array[0..-2].join(', ')}, and #{array[-1]}"
55
+ end
56
+
57
+ # Execute a block within the context of a variable enviroment
58
+ #
59
+ def with_environment(environment, value)
60
+ return yield unless environment
61
+
62
+ old_env = ENV[environment]
63
+ begin
64
+ ENV[environment] = value
65
+ yield
66
+ ensure
67
+ old_env ? ENV[environment] = old_env : ENV.delete(environment)
68
+ end
69
+ end
70
+
71
+ # Converts an integer representing bytes into a human readable format
72
+ #
73
+ def to_filesize(bytes, precision: 2, space: false)
74
+ to_si_scale(bytes, 'B', precision: precision, space: space, factor: 1024)
75
+ end
76
+
77
+ # Converts a number to a human readable format on the SI scale
78
+ #
79
+ def to_si_scale(number, unit = '', factor: 1000, precision: 2, space: false)
80
+ raise ArgumentError, "factor should only be 1000 or 1024" unless [1000, 1024].include?(factor)
81
+
82
+ small_scale = %w(m µ n p f a z y)
83
+ big_scale = %w(k M G T P E Z Y)
84
+ negative = number < 0
85
+ number = number.abs.to_f
86
+
87
+ if number == 0 || number.between?(1, factor)
88
+ prefix = ""
89
+ scale = 0
90
+ else
91
+ scale = Math.log(number, factor).floor
92
+ if number < 1
93
+ index = [-scale - 1, small_scale.length].min
94
+ scale = -(index + 1)
95
+ prefix = small_scale[index]
96
+ else
97
+ index = [scale - 1, big_scale.length].min
98
+ scale = index + 1
99
+ prefix = big_scale[index]
100
+ end
101
+ end
102
+
103
+ divider = (factor**scale)
104
+ fnum = (number / divider).round(precision)
105
+
106
+ # Trim useless decimal
107
+ fnum = fnum.to_i if (fnum.to_i.to_f * divider) == number
108
+
109
+ fnum = -fnum if negative
110
+ prefix = " " + prefix if space
111
+
112
+ "#{fnum}#{prefix}#{unit}"
113
+ end
114
+
115
+ # Dir.chdir, when invoked in block form, complains when we call chdir
116
+ # again recursively. There's no apparent good reason for this, so we
117
+ # simply implement our own block form of Dir.chdir here.
118
+ def with_dir(dir)
119
+ prev = Dir.pwd
120
+ Dir.chdir(dir)
121
+ yield
122
+ ensure
123
+ Dir.chdir(prev)
124
+ end
125
+
126
+ def with_tmp_dir
127
+ require 'fileutils'
128
+ dir = Dir.mktmpdir
129
+ with_dir(dir) do
130
+ yield(dir)
131
+ end
132
+ ensure
133
+ FileUtils.remove_entry(dir)
134
+ end
135
+
136
+ # Standard way of checking for CI / Tests
137
+ def testing?
138
+ ci? || ENV['TEST']
139
+ end
140
+
141
+ # Set only in IntegrationTest#session; indicates that the process was
142
+ # called by `session.execute` from an IntegrationTest subclass.
143
+ def integration_test_session?
144
+ ENV['INTEGRATION_TEST_SESSION']
145
+ end
146
+
147
+ # Standard way of checking for CI
148
+ def ci?
149
+ ENV['CI']
150
+ end
151
+
152
+ # Must call retry_after on the result in order to execute the block
153
+ #
154
+ # Example usage:
155
+ #
156
+ # CLI::Kit::Util.begin do
157
+ # might_raise_if_costly_prep_not_done()
158
+ # end.retry_after(ExpectedError) do
159
+ # costly_prep()
160
+ # end
161
+ def begin(&block_that_might_raise)
162
+ Retrier.new(block_that_might_raise)
163
+ end
164
+ end
165
+
166
+ class Retrier
167
+ def initialize(block_that_might_raise)
168
+ @block_that_might_raise = block_that_might_raise
169
+ end
170
+
171
+ def retry_after(exception = StandardError, retries: 1, &before_retry)
172
+ @block_that_might_raise.call
173
+ rescue exception => e
174
+ raise if (retries -= 1) < 0
175
+ if before_retry
176
+ if before_retry.arity == 0
177
+ yield
178
+ else
179
+ yield e
180
+ end
181
+ end
182
+ retry
183
+ end
184
+ end
185
+
186
+ private_constant :Retrier
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,5 @@
1
+ module CLI
2
+ module Kit
3
+ VERSION = "3.3.0"
4
+ end
5
+ end
@@ -0,0 +1 @@
1
+ 35e1b188f19b2ba0ab85bbf48ab983b1f72a361b
@@ -0,0 +1,187 @@
1
+ module CLI
2
+ module UI
3
+ autoload :ANSI, 'cli/ui/ansi'
4
+ autoload :Glyph, 'cli/ui/glyph'
5
+ autoload :Color, 'cli/ui/color'
6
+ autoload :Box, 'cli/ui/box'
7
+ autoload :Frame, 'cli/ui/frame'
8
+ autoload :Progress, 'cli/ui/progress'
9
+ autoload :Prompt, 'cli/ui/prompt'
10
+ autoload :Terminal, 'cli/ui/terminal'
11
+ autoload :Truncater, 'cli/ui/truncater'
12
+ autoload :Formatter, 'cli/ui/formatter'
13
+ autoload :Spinner, 'cli/ui/spinner'
14
+
15
+ # Convenience accessor to +CLI::UI::Spinner::SpinGroup+
16
+ SpinGroup = Spinner::SpinGroup
17
+
18
+ # Glyph resolution using +CLI::UI::Glyph.lookup+
19
+ # Look at the method signature for +Glyph.lookup+ for more details
20
+ #
21
+ # ==== Attributes
22
+ #
23
+ # * +handle+ - handle of the glyph to resolve
24
+ #
25
+ def self.glyph(handle)
26
+ CLI::UI::Glyph.lookup(handle)
27
+ end
28
+
29
+ # Color resolution using +CLI::UI::Color.lookup+
30
+ # Will lookup using +Color.lookup+ if a symbol, otherwise we assume it is a valid color and return it
31
+ #
32
+ # ==== Attributes
33
+ #
34
+ # * +input+ - color to resolve
35
+ #
36
+ def self.resolve_color(input)
37
+ case input
38
+ when Symbol
39
+ CLI::UI::Color.lookup(input)
40
+ else
41
+ input
42
+ end
43
+ end
44
+
45
+ # Conviencence Method for +CLI::UI::Prompt.confirm+
46
+ #
47
+ # ==== Attributes
48
+ #
49
+ # * +question+ - question to confirm
50
+ #
51
+ def self.confirm(question, **kwargs)
52
+ CLI::UI::Prompt.confirm(question, **kwargs)
53
+ end
54
+
55
+ # Conviencence Method for +CLI::UI::Prompt.ask+
56
+ #
57
+ # ==== Attributes
58
+ #
59
+ # * +question+ - question to ask
60
+ # * +kwargs+ - arugments for +Prompt.ask+
61
+ #
62
+ def self.ask(question, **kwargs)
63
+ CLI::UI::Prompt.ask(question, **kwargs)
64
+ end
65
+
66
+ # Conviencence Method to resolve text using +CLI::UI::Formatter.format+
67
+ # Check +CLI::UI::Formatter::SGR_MAP+ for available formatting options
68
+ #
69
+ # ==== Attributes
70
+ #
71
+ # * +input+ - input to format
72
+ # * +truncate_to+ - number of characters to truncate the string to (or nil)
73
+ #
74
+ def self.resolve_text(input, truncate_to: nil)
75
+ return input if input.nil?
76
+ formatted = CLI::UI::Formatter.new(input).format
77
+ return formatted unless truncate_to
78
+ return CLI::UI::Truncater.call(formatted, truncate_to)
79
+ end
80
+
81
+ # Conviencence Method to format text using +CLI::UI::Formatter.format+
82
+ # Check +CLI::UI::Formatter::SGR_MAP+ for available formatting options
83
+ #
84
+ # https://user-images.githubusercontent.com/3074765/33799827-6d0721a2-dd01-11e7-9ab5-c3d455264afe.png
85
+ # https://user-images.githubusercontent.com/3074765/33799847-9ec03fd0-dd01-11e7-93f7-5f5cc540e61e.png
86
+ #
87
+ # ==== Attributes
88
+ #
89
+ # * +input+ - input to format
90
+ #
91
+ # ==== Options
92
+ #
93
+ # * +enable_color+ - should color be used? default to true unless output is redirected.
94
+ #
95
+ def self.fmt(input, enable_color: enable_color?)
96
+ CLI::UI::Formatter.new(input).format(enable_color: enable_color)
97
+ end
98
+
99
+ # Conviencence Method for +CLI::UI::Frame.open+
100
+ #
101
+ # ==== Attributes
102
+ #
103
+ # * +args+ - arguments for +Frame.open+
104
+ # * +block+ - block for +Frame.open+
105
+ #
106
+ def self.frame(*args, &block)
107
+ CLI::UI::Frame.open(*args, &block)
108
+ end
109
+
110
+ # Conviencence Method for +CLI::UI::Spinner.spin+
111
+ #
112
+ # ==== Attributes
113
+ #
114
+ # * +args+ - arguments for +Spinner.open+
115
+ # * +block+ - block for +Spinner.open+
116
+ #
117
+ def self.spinner(*args, &block)
118
+ CLI::UI::Spinner.spin(*args, &block)
119
+ end
120
+
121
+ # Conviencence Method to override frame color using +CLI::UI::Frame.with_frame_color+
122
+ #
123
+ # ==== Attributes
124
+ #
125
+ # * +color+ - color to override to
126
+ # * +block+ - block for +Frame.with_frame_color_override+
127
+ #
128
+ def self.with_frame_color(color, &block)
129
+ CLI::UI::Frame.with_frame_color_override(color, &block)
130
+ end
131
+
132
+ # Duplicate output to a file path
133
+ #
134
+ # ==== Attributes
135
+ #
136
+ # * +path+ - path to duplicate output to
137
+ #
138
+ def self.log_output_to(path)
139
+ if CLI::UI::StdoutRouter.duplicate_output_to
140
+ raise "multiple logs not allowed"
141
+ end
142
+ CLI::UI::StdoutRouter.duplicate_output_to = File.open(path, 'w')
143
+ yield
144
+ ensure
145
+ if file_descriptor = CLI::UI::StdoutRouter.duplicate_output_to
146
+ file_descriptor.close
147
+ CLI::UI::StdoutRouter.duplicate_output_to = nil
148
+ end
149
+ end
150
+
151
+ # Disable all framing within a block
152
+ #
153
+ # ==== Attributes
154
+ #
155
+ # * +block+ - block in which to disable frames
156
+ #
157
+ def self.raw
158
+ prev = Thread.current[:no_cliui_frame_inset]
159
+ Thread.current[:no_cliui_frame_inset] = true
160
+ yield
161
+ ensure
162
+ Thread.current[:no_cliui_frame_inset] = prev
163
+ end
164
+
165
+ # Check whether colour is enabled in Formatter output. By default, colour
166
+ # is enabled when STDOUT is a TTY; that is, when output has not been
167
+ # redirected to another program or to a file.
168
+ #
169
+ def self.enable_color?
170
+ @enable_color
171
+ end
172
+
173
+ # Turn colour output in Formatter on or off.
174
+ #
175
+ # ==== Attributes
176
+ #
177
+ # * +bool+ - true or false; enable or disable colour.
178
+ #
179
+ def self.enable_color=(bool)
180
+ @enable_color = !!bool
181
+ end
182
+
183
+ self.enable_color = $stdout.tty?
184
+ end
185
+ end
186
+
187
+ require 'cli/ui/stdout_router'
@@ -0,0 +1,153 @@
1
+ require 'cli/ui'
2
+
3
+ module CLI
4
+ module UI
5
+ module ANSI
6
+ ESC = "\x1b"
7
+
8
+ # ANSI escape sequences (like \x1b[31m) have zero width.
9
+ # when calculating the padding width, we must exclude them.
10
+ # This also implements a basic version of utf8 character width calculation like
11
+ # we could get for real from something like utf8proc.
12
+ #
13
+ def self.printing_width(str)
14
+ zwj = false
15
+ strip_codes(str).codepoints.reduce(0) do |acc, cp|
16
+ if zwj
17
+ zwj = false
18
+ next acc
19
+ end
20
+ case cp
21
+ when 0x200d # zero-width joiner
22
+ zwj = true
23
+ acc
24
+ else
25
+ acc + 1
26
+ end
27
+ end
28
+ end
29
+
30
+ # Strips ANSI codes from a str
31
+ #
32
+ # ==== Attributes
33
+ #
34
+ # - +str+ - The string from which to strip codes
35
+ #
36
+ def self.strip_codes(str)
37
+ str.gsub(/\x1b\[[\d;]+[A-z]|\r/, '')
38
+ end
39
+
40
+ # Returns an ANSI control sequence
41
+ #
42
+ # ==== Attributes
43
+ #
44
+ # - +args+ - Argument to pass to the ANSI control sequence
45
+ # - +cmd+ - ANSI control sequence Command
46
+ #
47
+ def self.control(args, cmd)
48
+ ESC + "[" + args + cmd
49
+ end
50
+
51
+ # https://en.wikipedia.org/wiki/ANSI_escape_code#graphics
52
+ def self.sgr(params)
53
+ control(params.to_s, 'm')
54
+ end
55
+
56
+ # Cursor Movement
57
+
58
+ # Move the cursor up n lines
59
+ #
60
+ # ==== Attributes
61
+ #
62
+ # * +n+ - number of lines by which to move the cursor up
63
+ #
64
+ def self.cursor_up(n = 1)
65
+ return '' if n.zero?
66
+ control(n.to_s, 'A')
67
+ end
68
+
69
+ # Move the cursor down n lines
70
+ #
71
+ # ==== Attributes
72
+ #
73
+ # * +n+ - number of lines by which to move the cursor down
74
+ #
75
+ def self.cursor_down(n = 1)
76
+ return '' if n.zero?
77
+ control(n.to_s, 'B')
78
+ end
79
+
80
+ # Move the cursor forward n columns
81
+ #
82
+ # ==== Attributes
83
+ #
84
+ # * +n+ - number of columns by which to move the cursor forward
85
+ #
86
+ def self.cursor_forward(n = 1)
87
+ return '' if n.zero?
88
+ control(n.to_s, 'C')
89
+ end
90
+
91
+ # Move the cursor back n columns
92
+ #
93
+ # ==== Attributes
94
+ #
95
+ # * +n+ - number of columns by which to move the cursor back
96
+ #
97
+ def self.cursor_back(n = 1)
98
+ return '' if n.zero?
99
+ control(n.to_s, 'D')
100
+ end
101
+
102
+ # Move the cursor to a specific column
103
+ #
104
+ # ==== Attributes
105
+ #
106
+ # * +n+ - The column to move to
107
+ #
108
+ def self.cursor_horizontal_absolute(n = 1)
109
+ control(n.to_s, 'G')
110
+ end
111
+
112
+ # Show the cursor
113
+ #
114
+ def self.show_cursor
115
+ control('', "?25h")
116
+ end
117
+
118
+ # Hide the cursor
119
+ #
120
+ def self.hide_cursor
121
+ control('', "?25l")
122
+ end
123
+
124
+ # Save the cursor position
125
+ #
126
+ def self.cursor_save
127
+ control('', 's')
128
+ end
129
+
130
+ # Restore the saved cursor position
131
+ #
132
+ def self.cursor_restore
133
+ control('', 'u')
134
+ end
135
+
136
+ # Move to the next line
137
+ #
138
+ def self.next_line
139
+ cursor_down + control('1', 'G')
140
+ end
141
+
142
+ # Move to the previous line
143
+ #
144
+ def self.previous_line
145
+ cursor_up + control('1', 'G')
146
+ end
147
+
148
+ def self.clear_to_end_of_line
149
+ control('', 'K')
150
+ end
151
+ end
152
+ end
153
+ end