alchemrest 3.1.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 (245) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +22 -0
  4. data/.rubocop_todo.yml +242 -0
  5. data/.ruby-version +1 -0
  6. data/Appraisals +19 -0
  7. data/Gemfile +6 -0
  8. data/Gemfile.lock +378 -0
  9. data/Rakefile +29 -0
  10. data/alchemrest.gemspec +71 -0
  11. data/coach.yml +5 -0
  12. data/examples/bank_api/client.rb +31 -0
  13. data/examples/bank_api/data/account.rb +21 -0
  14. data/examples/bank_api/data/ach.rb +16 -0
  15. data/examples/bank_api/data/business_account.rb +22 -0
  16. data/examples/bank_api/data/card.rb +21 -0
  17. data/examples/bank_api/data/check.rb +19 -0
  18. data/examples/bank_api/data/product.rb +20 -0
  19. data/examples/bank_api/data/transaction.rb +49 -0
  20. data/examples/bank_api/data/user.rb +27 -0
  21. data/examples/bank_api/factories.rb +68 -0
  22. data/examples/bank_api/graph_visualization.rb +45 -0
  23. data/examples/bank_api/positive_interest_string.rb +33 -0
  24. data/examples/bank_api/requests/delete_user.rb +17 -0
  25. data/examples/bank_api/requests/get_business_account.rb +24 -0
  26. data/examples/bank_api/requests/get_products.rb +12 -0
  27. data/examples/bank_api/requests/get_transactions.rb +34 -0
  28. data/examples/bank_api/requests/get_user.rb +19 -0
  29. data/examples/bank_api/requests/post_transaction.rb +20 -0
  30. data/examples/bank_api/requests/update_user.rb +28 -0
  31. data/examples/bank_api/root.rb +52 -0
  32. data/examples/bank_api.rb +33 -0
  33. data/gemfiles/faraday_2.gemfile +9 -0
  34. data/gemfiles/faraday_2.gemfile.lock +363 -0
  35. data/gemfiles/rails_7_0.gemfile.lock +341 -0
  36. data/gemfiles/rails_7_2.gemfile +9 -0
  37. data/gemfiles/rails_7_2.gemfile.lock +384 -0
  38. data/gemfiles/rails_8_0.gemfile +9 -0
  39. data/gemfiles/rails_8_0.gemfile.lock +385 -0
  40. data/lib/alchemrest/circuit_breaker.rb +84 -0
  41. data/lib/alchemrest/client/configuration/connection.rb +83 -0
  42. data/lib/alchemrest/client/configuration.rb +89 -0
  43. data/lib/alchemrest/client.rb +48 -0
  44. data/lib/alchemrest/cop.rb +8 -0
  45. data/lib/alchemrest/data/capture_configuration.rb +77 -0
  46. data/lib/alchemrest/data/field.rb +36 -0
  47. data/lib/alchemrest/data/graph.rb +40 -0
  48. data/lib/alchemrest/data/record.rb +60 -0
  49. data/lib/alchemrest/data/schema.rb +80 -0
  50. data/lib/alchemrest/data.rb +9 -0
  51. data/lib/alchemrest/endpoint_definition.rb +47 -0
  52. data/lib/alchemrest/error.rb +122 -0
  53. data/lib/alchemrest/factory_bot.rb +64 -0
  54. data/lib/alchemrest/faraday_middleware/external_api_instrumentation.rb +24 -0
  55. data/lib/alchemrest/faraday_middleware/json_parser.rb +30 -0
  56. data/lib/alchemrest/faraday_middleware/kill_switch.rb +22 -0
  57. data/lib/alchemrest/faraday_middleware/underscore_response.rb +24 -0
  58. data/lib/alchemrest/hash_path.rb +81 -0
  59. data/lib/alchemrest/http_request.rb +75 -0
  60. data/lib/alchemrest/kill_switch/adapters.rb +88 -0
  61. data/lib/alchemrest/kill_switch.rb +31 -0
  62. data/lib/alchemrest/railtie.rb +25 -0
  63. data/lib/alchemrest/request/endpoint.rb +29 -0
  64. data/lib/alchemrest/request/returns.rb +46 -0
  65. data/lib/alchemrest/request.rb +80 -0
  66. data/lib/alchemrest/request_definition/builder.rb +13 -0
  67. data/lib/alchemrest/request_definition.rb +26 -0
  68. data/lib/alchemrest/response/pipeline/extract_payload.rb +64 -0
  69. data/lib/alchemrest/response/pipeline/final.rb +11 -0
  70. data/lib/alchemrest/response/pipeline/omit.rb +46 -0
  71. data/lib/alchemrest/response/pipeline/sanitize.rb +59 -0
  72. data/lib/alchemrest/response/pipeline/transform.rb +26 -0
  73. data/lib/alchemrest/response/pipeline/was_successful.rb +29 -0
  74. data/lib/alchemrest/response/pipeline.rb +71 -0
  75. data/lib/alchemrest/response.rb +73 -0
  76. data/lib/alchemrest/response_captured_handler.rb +68 -0
  77. data/lib/alchemrest/result/halt.rb +15 -0
  78. data/lib/alchemrest/result/try_helpers.rb +16 -0
  79. data/lib/alchemrest/result.rb +128 -0
  80. data/lib/alchemrest/root.rb +77 -0
  81. data/lib/alchemrest/transforms/base_to_type_transform_registry.rb +42 -0
  82. data/lib/alchemrest/transforms/constrainable.rb +41 -0
  83. data/lib/alchemrest/transforms/constraint/block.rb +22 -0
  84. data/lib/alchemrest/transforms/constraint/greater_than.rb +19 -0
  85. data/lib/alchemrest/transforms/constraint/greater_than_or_eq.rb +19 -0
  86. data/lib/alchemrest/transforms/constraint/in_list.rb +19 -0
  87. data/lib/alchemrest/transforms/constraint/is_instance_of.rb +19 -0
  88. data/lib/alchemrest/transforms/constraint/is_uuid.rb +19 -0
  89. data/lib/alchemrest/transforms/constraint/less_than.rb +19 -0
  90. data/lib/alchemrest/transforms/constraint/less_than_or_eq.rb +19 -0
  91. data/lib/alchemrest/transforms/constraint/matches_regex.rb +19 -0
  92. data/lib/alchemrest/transforms/constraint/max_length.rb +19 -0
  93. data/lib/alchemrest/transforms/constraint/min_length.rb +19 -0
  94. data/lib/alchemrest/transforms/constraint.rb +17 -0
  95. data/lib/alchemrest/transforms/constraint_builder/for_number.rb +25 -0
  96. data/lib/alchemrest/transforms/constraint_builder/for_string.rb +21 -0
  97. data/lib/alchemrest/transforms/constraint_builder.rb +15 -0
  98. data/lib/alchemrest/transforms/date_transform.rb +30 -0
  99. data/lib/alchemrest/transforms/enum.rb +52 -0
  100. data/lib/alchemrest/transforms/epoch_time.rb +32 -0
  101. data/lib/alchemrest/transforms/from_chain.rb +15 -0
  102. data/lib/alchemrest/transforms/from_number/to_type_transform_registry.rb +18 -0
  103. data/lib/alchemrest/transforms/from_number.rb +47 -0
  104. data/lib/alchemrest/transforms/from_string/to_type_transform_registry.rb +17 -0
  105. data/lib/alchemrest/transforms/from_string.rb +36 -0
  106. data/lib/alchemrest/transforms/from_type/empty_to_type_transform_registry.rb +14 -0
  107. data/lib/alchemrest/transforms/from_type.rb +64 -0
  108. data/lib/alchemrest/transforms/iso_time.rb +58 -0
  109. data/lib/alchemrest/transforms/json_number.rb +26 -0
  110. data/lib/alchemrest/transforms/loose_hash.rb +96 -0
  111. data/lib/alchemrest/transforms/money_transform.rb +42 -0
  112. data/lib/alchemrest/transforms/number.rb +27 -0
  113. data/lib/alchemrest/transforms/output_type.rb +65 -0
  114. data/lib/alchemrest/transforms/to_decimal.rb +22 -0
  115. data/lib/alchemrest/transforms/to_type/from_string_to_time_selector.rb +29 -0
  116. data/lib/alchemrest/transforms/to_type/transforms_selector.rb +61 -0
  117. data/lib/alchemrest/transforms/to_type.rb +86 -0
  118. data/lib/alchemrest/transforms/typed.rb +32 -0
  119. data/lib/alchemrest/transforms/union.rb +44 -0
  120. data/lib/alchemrest/transforms/with_constraint.rb +26 -0
  121. data/lib/alchemrest/transforms.rb +93 -0
  122. data/lib/alchemrest/url_builder/encoders.rb +39 -0
  123. data/lib/alchemrest/url_builder/options.rb +33 -0
  124. data/lib/alchemrest/url_builder.rb +31 -0
  125. data/lib/alchemrest/version.rb +5 -0
  126. data/lib/alchemrest/webmock_helpers.rb +27 -0
  127. data/lib/alchemrest.rb +159 -0
  128. data/lib/generators/alchemrest/kill_switch_migration_generator.rb +27 -0
  129. data/lib/generators/alchemrest/templates/kill_switch_migration.rb.erb +17 -0
  130. data/lib/rubocop/cop/alchemrest/define_request_using_with_params.rb +53 -0
  131. data/lib/rubocop/cop/alchemrest/endpoint_definition_using_generic_params.rb +55 -0
  132. data/lib/rubocop/cop/alchemrest/request_hash_returning_block.rb +54 -0
  133. data/lib/rubocop/cop/alchemrest/time_transform_with_no_zone.rb +56 -0
  134. data/lib/tapioca/dsl/compilers/alchemrest_data.rb +84 -0
  135. data/lib/tapioca/dsl/compilers/alchemrest_root.rb +68 -0
  136. data/mutant.yml +16 -0
  137. data/rbi/alchemrest/result.rbi +80 -0
  138. data/rbi/alchemrest.rbi +246 -0
  139. data/sorbet/config +5 -0
  140. data/sorbet/rbi/gems/.gitattributes +1 -0
  141. data/sorbet/rbi/gems/abstract_type@0.0.7.rbi +41 -0
  142. data/sorbet/rbi/gems/actionpack@8.0.4.rbi +11733 -0
  143. data/sorbet/rbi/gems/actionview@8.0.4.rbi +6560 -0
  144. data/sorbet/rbi/gems/activemodel@8.0.4.rbi +2891 -0
  145. data/sorbet/rbi/gems/activesupport@8.0.4.rbi +9621 -0
  146. data/sorbet/rbi/gems/adamantium@0.2.0.rbi +144 -0
  147. data/sorbet/rbi/gems/addressable@2.8.7.rbi +779 -0
  148. data/sorbet/rbi/gems/anima@0.3.2.rbi +103 -0
  149. data/sorbet/rbi/gems/ast@2.4.2.rbi +107 -0
  150. data/sorbet/rbi/gems/base64@0.3.0.rbi +52 -0
  151. data/sorbet/rbi/gems/benchmark@0.5.0.rbi +153 -0
  152. data/sorbet/rbi/gems/bigdecimal@3.3.1.rbi +77 -0
  153. data/sorbet/rbi/gems/builder@3.3.0.rbi +9 -0
  154. data/sorbet/rbi/gems/circuitbox@2.0.0.rbi +297 -0
  155. data/sorbet/rbi/gems/concord@0.1.6.rbi +51 -0
  156. data/sorbet/rbi/gems/concurrent-ruby@1.3.5.rbi +4716 -0
  157. data/sorbet/rbi/gems/connection_pool@2.5.4.rbi +9 -0
  158. data/sorbet/rbi/gems/crack@1.0.0.rbi +110 -0
  159. data/sorbet/rbi/gems/crass@1.0.6.rbi +294 -0
  160. data/sorbet/rbi/gems/date@3.4.1.rbi +58 -0
  161. data/sorbet/rbi/gems/drb@2.2.3.rbi +639 -0
  162. data/sorbet/rbi/gems/equalizer@0.0.11.rbi +38 -0
  163. data/sorbet/rbi/gems/erubi@1.13.1.rbi +85 -0
  164. data/sorbet/rbi/gems/factory_bot@6.5.0.rbi +1529 -0
  165. data/sorbet/rbi/gems/faraday-em_http@1.0.0.rbi +181 -0
  166. data/sorbet/rbi/gems/faraday-em_synchrony@1.0.1.rbi +120 -0
  167. data/sorbet/rbi/gems/faraday-excon@1.1.0.rbi +128 -0
  168. data/sorbet/rbi/gems/faraday-httpclient@1.0.1.rbi +123 -0
  169. data/sorbet/rbi/gems/faraday-multipart@1.2.0.rbi +190 -0
  170. data/sorbet/rbi/gems/faraday-net_http@1.0.2.rbi +140 -0
  171. data/sorbet/rbi/gems/faraday-net_http_persistent@1.2.0.rbi +116 -0
  172. data/sorbet/rbi/gems/faraday-patron@1.0.0.rbi +119 -0
  173. data/sorbet/rbi/gems/faraday-rack@1.0.0.rbi +113 -0
  174. data/sorbet/rbi/gems/faraday-retry@1.0.3.rbi +149 -0
  175. data/sorbet/rbi/gems/faraday@1.10.5.rbi +1620 -0
  176. data/sorbet/rbi/gems/hansi@0.2.1.rbi +9 -0
  177. data/sorbet/rbi/gems/hashdiff@1.1.2.rbi +174 -0
  178. data/sorbet/rbi/gems/i18n@1.14.7.rbi +1328 -0
  179. data/sorbet/rbi/gems/ice_nine@0.11.2.rbi +145 -0
  180. data/sorbet/rbi/gems/io-console@0.8.0.rbi +9 -0
  181. data/sorbet/rbi/gems/json@2.9.1.rbi +282 -0
  182. data/sorbet/rbi/gems/language_server-protocol@3.17.0.3.rbi +8057 -0
  183. data/sorbet/rbi/gems/logger@1.7.0.rbi +260 -0
  184. data/sorbet/rbi/gems/loofah@2.24.0.rbi +571 -0
  185. data/sorbet/rbi/gems/memoizable@0.4.2.rbi +131 -0
  186. data/sorbet/rbi/gems/memosa@0.8.2.rbi +185 -0
  187. data/sorbet/rbi/gems/minitest@5.26.0.rbi +824 -0
  188. data/sorbet/rbi/gems/money@6.19.0.rbi +815 -0
  189. data/sorbet/rbi/gems/morpher@0.4.2.rbi +388 -0
  190. data/sorbet/rbi/gems/mprelude@0.1.0.rbi +140 -0
  191. data/sorbet/rbi/gems/multi_json@1.15.0.rbi +180 -0
  192. data/sorbet/rbi/gems/multipart-post@2.4.1.rbi +154 -0
  193. data/sorbet/rbi/gems/mustermann-contrib@3.0.3.rbi +9 -0
  194. data/sorbet/rbi/gems/mustermann@3.0.3.rbi +809 -0
  195. data/sorbet/rbi/gems/netrc@0.11.0.rbi +112 -0
  196. data/sorbet/rbi/gems/nokogiri@1.19.1.rbi +3412 -0
  197. data/sorbet/rbi/gems/parallel@1.26.3.rbi +234 -0
  198. data/sorbet/rbi/gems/parser@3.3.7.0.rbi +4877 -0
  199. data/sorbet/rbi/gems/pp@0.6.2.rbi +176 -0
  200. data/sorbet/rbi/gems/prettyprint@0.2.0.rbi +155 -0
  201. data/sorbet/rbi/gems/prism@1.5.1.rbi +26368 -0
  202. data/sorbet/rbi/gems/procto@0.0.3.rbi +9 -0
  203. data/sorbet/rbi/gems/psych@5.2.3.rbi +806 -0
  204. data/sorbet/rbi/gems/public_suffix@6.0.1.rbi +267 -0
  205. data/sorbet/rbi/gems/racc@1.8.1.rbi +120 -0
  206. data/sorbet/rbi/gems/rack-session@2.1.1.rbi +458 -0
  207. data/sorbet/rbi/gems/rack-test@2.2.0.rbi +405 -0
  208. data/sorbet/rbi/gems/rack@3.1.14.rbi +2774 -0
  209. data/sorbet/rbi/gems/rackup@2.2.1.rbi +132 -0
  210. data/sorbet/rbi/gems/rails-dom-testing@2.2.0.rbi +266 -0
  211. data/sorbet/rbi/gems/rails-html-sanitizer@1.6.2.rbi +545 -0
  212. data/sorbet/rbi/gems/railties@8.0.4.rbi +2150 -0
  213. data/sorbet/rbi/gems/rainbow@3.1.1.rbi +333 -0
  214. data/sorbet/rbi/gems/rake@13.2.1.rbi +2054 -0
  215. data/sorbet/rbi/gems/rbi@0.2.3.rbi +3961 -0
  216. data/sorbet/rbi/gems/rdoc@6.13.1.rbi +6784 -0
  217. data/sorbet/rbi/gems/regexp_parser@2.11.3.rbi +3020 -0
  218. data/sorbet/rbi/gems/reline@0.6.0.rbi +9 -0
  219. data/sorbet/rbi/gems/rexml@3.4.2.rbi +1777 -0
  220. data/sorbet/rbi/gems/rubocop-ast@1.38.0.rbi +5293 -0
  221. data/sorbet/rbi/gems/rubocop@1.71.1.rbi +31846 -0
  222. data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +980 -0
  223. data/sorbet/rbi/gems/ruby2_keywords@0.0.5.rbi +9 -0
  224. data/sorbet/rbi/gems/securerandom@0.4.1.rbi +33 -0
  225. data/sorbet/rbi/gems/sentry-ruby@5.22.1.rbi +3782 -0
  226. data/sorbet/rbi/gems/spoom@1.5.1.rbi +4321 -0
  227. data/sorbet/rbi/gems/stringio@3.1.2.rbi +9 -0
  228. data/sorbet/rbi/gems/tapioca@0.16.8.rbi +3399 -0
  229. data/sorbet/rbi/gems/thor@1.3.2.rbi +2012 -0
  230. data/sorbet/rbi/gems/thread_safe@0.3.6.rbi +711 -0
  231. data/sorbet/rbi/gems/timeout@0.4.4.rbi +80 -0
  232. data/sorbet/rbi/gems/tsort@0.2.0.rbi +50 -0
  233. data/sorbet/rbi/gems/tzinfo@2.0.6.rbi +1677 -0
  234. data/sorbet/rbi/gems/unicode-display_width@2.6.0.rbi +62 -0
  235. data/sorbet/rbi/gems/uri@1.1.0.rbi +760 -0
  236. data/sorbet/rbi/gems/useragent@0.16.11.rbi +9 -0
  237. data/sorbet/rbi/gems/webmock@3.24.0.rbi +1362 -0
  238. data/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +345 -0
  239. data/sorbet/rbi/gems/yard@0.9.37.rbi +8795 -0
  240. data/sorbet/rbi/gems/zeitwerk@2.7.1.rbi +589 -0
  241. data/sorbet/tapioca/config.yml +45 -0
  242. data/sorbet/tapioca/require.rb +8 -0
  243. data/sorbet/tapioca/sorbet/rbi/dsl/.gitattributes +1 -0
  244. data/sorbet/tapioca/sorbet/rbi/dsl/active_support/callbacks.rbi +23 -0
  245. metadata +737 -0
@@ -0,0 +1,385 @@
1
+ PATH
2
+ remote: ..
3
+ specs:
4
+ alchemrest (3.1.0)
5
+ activerecord (>= 7.2, < 8.1)
6
+ activesupport (>= 7.2, < 8.1)
7
+ circuitbox (~> 2.0.0)
8
+ faraday (>= 1.10, < 3.0)
9
+ memosa (>= 0.8.2)
10
+ money (>= 6.0)
11
+ morpher (>= 0.4.1)
12
+ multi_json (~> 1.0)
13
+ mustermann-contrib (>= 1.0)
14
+ railties (>= 7.2, < 8.1)
15
+ sentry-ruby
16
+ sorbet-runtime (>= 0.5.0)
17
+
18
+ GEM
19
+ remote: https://rubygems.org/
20
+ specs:
21
+ abstract_type (0.0.7)
22
+ actionpack (8.0.1)
23
+ actionview (= 8.0.1)
24
+ activesupport (= 8.0.1)
25
+ nokogiri (>= 1.8.5)
26
+ rack (>= 2.2.4)
27
+ rack-session (>= 1.0.1)
28
+ rack-test (>= 0.6.3)
29
+ rails-dom-testing (~> 2.2)
30
+ rails-html-sanitizer (~> 1.6)
31
+ useragent (~> 0.16)
32
+ actionview (8.0.1)
33
+ activesupport (= 8.0.1)
34
+ builder (~> 3.1)
35
+ erubi (~> 1.11)
36
+ rails-dom-testing (~> 2.2)
37
+ rails-html-sanitizer (~> 1.6)
38
+ activemodel (8.0.1)
39
+ activesupport (= 8.0.1)
40
+ activerecord (8.0.1)
41
+ activemodel (= 8.0.1)
42
+ activesupport (= 8.0.1)
43
+ timeout (>= 0.4.0)
44
+ activesupport (8.0.1)
45
+ base64
46
+ benchmark (>= 0.3)
47
+ bigdecimal
48
+ concurrent-ruby (~> 1.0, >= 1.3.1)
49
+ connection_pool (>= 2.2.5)
50
+ drb
51
+ i18n (>= 1.6, < 2)
52
+ logger (>= 1.4.2)
53
+ minitest (>= 5.1)
54
+ securerandom (>= 0.3)
55
+ tzinfo (~> 2.0, >= 2.0.5)
56
+ uri (>= 0.13.1)
57
+ adamantium (0.2.0)
58
+ ice_nine (~> 0.11.0)
59
+ memoizable (~> 0.4.0)
60
+ addressable (2.8.7)
61
+ public_suffix (>= 2.0.2, < 7.0)
62
+ anima (0.3.2)
63
+ abstract_type (~> 0.0.7)
64
+ adamantium (~> 0.2)
65
+ equalizer (~> 0.0.11)
66
+ appraisal (2.5.0)
67
+ bundler
68
+ rake
69
+ thor (>= 0.14.0)
70
+ ast (2.4.2)
71
+ base64 (0.2.0)
72
+ benchmark (0.4.0)
73
+ betterlint (1.18.0)
74
+ rubocop (~> 1.71)
75
+ rubocop-graphql (~> 1.5)
76
+ rubocop-performance (~> 1.23)
77
+ rubocop-rails (~> 2.29)
78
+ rubocop-rake (~> 0.6)
79
+ rubocop-rspec (~> 2.29)
80
+ bigdecimal (3.1.9)
81
+ builder (3.3.0)
82
+ circuitbox (2.0.0)
83
+ coderay (1.1.3)
84
+ combustion (1.5.0)
85
+ activesupport (>= 3.0.0)
86
+ railties (>= 3.0.0)
87
+ thor (>= 0.14.6)
88
+ concord (0.1.6)
89
+ adamantium (~> 0.2.0)
90
+ equalizer (~> 0.0.9)
91
+ concurrent-ruby (1.3.5)
92
+ connection_pool (2.5.0)
93
+ crack (1.0.0)
94
+ bigdecimal
95
+ rexml
96
+ crass (1.0.6)
97
+ date (3.4.1)
98
+ diff-lcs (1.6.2)
99
+ drb (2.2.1)
100
+ equalizer (0.0.11)
101
+ erubi (1.13.1)
102
+ factory_bot (6.5.0)
103
+ activesupport (>= 5.0.0)
104
+ faraday (1.10.4)
105
+ faraday-em_http (~> 1.0)
106
+ faraday-em_synchrony (~> 1.0)
107
+ faraday-excon (~> 1.1)
108
+ faraday-httpclient (~> 1.0)
109
+ faraday-multipart (~> 1.0)
110
+ faraday-net_http (~> 1.0)
111
+ faraday-net_http_persistent (~> 1.0)
112
+ faraday-patron (~> 1.0)
113
+ faraday-rack (~> 1.0)
114
+ faraday-retry (~> 1.0)
115
+ ruby2_keywords (>= 0.0.4)
116
+ faraday-em_http (1.0.0)
117
+ faraday-em_synchrony (1.0.0)
118
+ faraday-excon (1.1.0)
119
+ faraday-httpclient (1.0.1)
120
+ faraday-multipart (1.1.0)
121
+ multipart-post (~> 2.0)
122
+ faraday-net_http (1.0.2)
123
+ faraday-net_http_persistent (1.2.0)
124
+ faraday-patron (1.0.0)
125
+ faraday-rack (1.0.0)
126
+ faraday-retry (1.0.3)
127
+ hansi (0.2.1)
128
+ hashdiff (1.1.2)
129
+ i18n (1.14.6)
130
+ concurrent-ruby (~> 1.0)
131
+ ice_nine (0.11.2)
132
+ io-console (0.8.0)
133
+ irb (1.15.2)
134
+ pp (>= 0.6.0)
135
+ rdoc (>= 4.0.0)
136
+ reline (>= 0.4.2)
137
+ json (2.9.1)
138
+ language_server-protocol (3.17.0.3)
139
+ logger (1.6.5)
140
+ loofah (2.24.0)
141
+ crass (~> 1.0.2)
142
+ nokogiri (>= 1.12.0)
143
+ memoizable (0.4.2)
144
+ thread_safe (~> 0.3, >= 0.3.1)
145
+ memosa (0.8.2)
146
+ method_source (1.1.0)
147
+ minitest (5.25.4)
148
+ moneta (1.6.0)
149
+ money (6.19.0)
150
+ i18n (>= 0.6.4, <= 2)
151
+ morpher (0.4.2)
152
+ abstract_type (~> 0.0.7)
153
+ adamantium (~> 0.2.0)
154
+ anima (~> 0.3.0)
155
+ concord (~> 0.1.5)
156
+ equalizer (~> 0.0.9)
157
+ mprelude (~> 0.1.0)
158
+ procto (~> 0.0.2)
159
+ mprelude (0.1.0)
160
+ abstract_type (~> 0.0.7)
161
+ adamantium (~> 0.2.0)
162
+ concord (~> 0.1.5)
163
+ equalizer (~> 0.0.9)
164
+ ice_nine (~> 0.11.1)
165
+ procto (~> 0.0.2)
166
+ multi_json (1.15.0)
167
+ multipart-post (2.4.1)
168
+ mustermann (3.0.3)
169
+ ruby2_keywords (~> 0.0.1)
170
+ mustermann-contrib (3.0.3)
171
+ hansi (~> 0.2.0)
172
+ mustermann (= 3.0.3)
173
+ mutant (0.13.4)
174
+ diff-lcs (~> 1.3)
175
+ irb (~> 1.15.2)
176
+ parser (~> 3.3.0)
177
+ regexp_parser (~> 2.10)
178
+ sorbet-runtime (~> 0.5.0)
179
+ unparser (~> 0.8.0)
180
+ mutant-rspec (0.13.4)
181
+ mutant (= 0.13.4)
182
+ rspec-core (>= 3.8.0, < 4.0.0)
183
+ netrc (0.11.0)
184
+ nokogiri (1.18.8-aarch64-linux-gnu)
185
+ racc (~> 1.4)
186
+ nokogiri (1.18.8-aarch64-linux-musl)
187
+ racc (~> 1.4)
188
+ nokogiri (1.18.8-arm64-darwin)
189
+ racc (~> 1.4)
190
+ nokogiri (1.18.8-x86_64-darwin)
191
+ racc (~> 1.4)
192
+ nokogiri (1.18.8-x86_64-linux-gnu)
193
+ racc (~> 1.4)
194
+ nokogiri (1.18.8-x86_64-linux-musl)
195
+ racc (~> 1.4)
196
+ parallel (1.26.3)
197
+ parser (3.3.7.0)
198
+ ast (~> 2.4.1)
199
+ racc
200
+ pg (1.5.9)
201
+ pp (0.6.2)
202
+ prettyprint
203
+ prettyprint (0.2.0)
204
+ prism (1.5.1)
205
+ procto (0.0.3)
206
+ pry (0.15.2)
207
+ coderay (~> 1.1)
208
+ method_source (~> 1.0)
209
+ psych (5.2.3)
210
+ date
211
+ stringio
212
+ public_suffix (6.0.1)
213
+ racc (1.8.1)
214
+ rack (3.1.14)
215
+ rack-session (2.1.1)
216
+ base64 (>= 0.1.0)
217
+ rack (>= 3.0.0)
218
+ rack-test (2.2.0)
219
+ rack (>= 1.3)
220
+ rackup (2.2.1)
221
+ rack (>= 3)
222
+ rails-dom-testing (2.2.0)
223
+ activesupport (>= 5.0.0)
224
+ minitest
225
+ nokogiri (>= 1.6)
226
+ rails-html-sanitizer (1.6.2)
227
+ loofah (~> 2.21)
228
+ nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
229
+ railties (8.0.1)
230
+ actionpack (= 8.0.1)
231
+ activesupport (= 8.0.1)
232
+ irb (~> 1.13)
233
+ rackup (>= 1.0.0)
234
+ rake (>= 12.2)
235
+ thor (~> 1.0, >= 1.2.2)
236
+ zeitwerk (~> 2.6)
237
+ rainbow (3.1.1)
238
+ rake (13.2.1)
239
+ rbi (0.2.3)
240
+ prism (~> 1.0)
241
+ sorbet-runtime (>= 0.5.9204)
242
+ rdoc (6.13.1)
243
+ psych (>= 4.0.0)
244
+ regexp_parser (2.11.3)
245
+ reline (0.6.0)
246
+ io-console (~> 0.5)
247
+ rexml (3.4.0)
248
+ rspec (3.13.0)
249
+ rspec-core (~> 3.13.0)
250
+ rspec-expectations (~> 3.13.0)
251
+ rspec-mocks (~> 3.13.0)
252
+ rspec-core (3.13.2)
253
+ rspec-support (~> 3.13.0)
254
+ rspec-expectations (3.13.3)
255
+ diff-lcs (>= 1.2.0, < 2.0)
256
+ rspec-support (~> 3.13.0)
257
+ rspec-mocks (3.13.2)
258
+ diff-lcs (>= 1.2.0, < 2.0)
259
+ rspec-support (~> 3.13.0)
260
+ rspec-support (3.13.2)
261
+ rspec_junit_formatter (0.6.0)
262
+ rspec-core (>= 2, < 4, != 2.12.0)
263
+ rubocop (1.71.1)
264
+ json (~> 2.3)
265
+ language_server-protocol (>= 3.17.0)
266
+ parallel (~> 1.10)
267
+ parser (>= 3.3.0.2)
268
+ rainbow (>= 2.2.2, < 4.0)
269
+ regexp_parser (>= 2.9.3, < 3.0)
270
+ rubocop-ast (>= 1.38.0, < 2.0)
271
+ ruby-progressbar (~> 1.7)
272
+ unicode-display_width (>= 2.4.0, < 4.0)
273
+ rubocop-ast (1.38.0)
274
+ parser (>= 3.3.1.0)
275
+ rubocop-capybara (2.21.0)
276
+ rubocop (~> 1.41)
277
+ rubocop-factory_bot (2.26.1)
278
+ rubocop (~> 1.61)
279
+ rubocop-graphql (1.5.4)
280
+ rubocop (>= 1.50, < 2)
281
+ rubocop-performance (1.23.1)
282
+ rubocop (>= 1.48.1, < 2.0)
283
+ rubocop-ast (>= 1.31.1, < 2.0)
284
+ rubocop-rails (2.29.1)
285
+ activesupport (>= 4.2.0)
286
+ rack (>= 1.1)
287
+ rubocop (>= 1.52.0, < 2.0)
288
+ rubocop-ast (>= 1.31.1, < 2.0)
289
+ rubocop-rake (0.6.0)
290
+ rubocop (~> 1.0)
291
+ rubocop-rspec (2.31.0)
292
+ rubocop (~> 1.40)
293
+ rubocop-capybara (~> 2.17)
294
+ rubocop-factory_bot (~> 2.22)
295
+ rubocop-rspec_rails (~> 2.28)
296
+ rubocop-rspec_rails (2.29.1)
297
+ rubocop (~> 1.61)
298
+ ruby-progressbar (1.13.0)
299
+ ruby2_keywords (0.0.5)
300
+ securerandom (0.4.1)
301
+ sentry-ruby (5.22.1)
302
+ bigdecimal
303
+ concurrent-ruby (~> 1.0, >= 1.0.2)
304
+ sorbet (0.5.11763)
305
+ sorbet-static (= 0.5.11763)
306
+ sorbet-runtime (0.5.11763)
307
+ sorbet-static (0.5.11763-aarch64-linux)
308
+ sorbet-static (0.5.11763-universal-darwin)
309
+ sorbet-static (0.5.11763-x86_64-linux)
310
+ sorbet-static-and-runtime (0.5.11763)
311
+ sorbet (= 0.5.11763)
312
+ sorbet-runtime (= 0.5.11763)
313
+ spoom (1.5.1)
314
+ erubi (>= 1.10.0)
315
+ prism (>= 0.28.0)
316
+ sorbet-static-and-runtime (>= 0.5.10187)
317
+ thor (>= 0.19.2)
318
+ stringio (3.1.2)
319
+ tapioca (0.16.8)
320
+ benchmark
321
+ bundler (>= 2.2.25)
322
+ netrc (>= 0.11.0)
323
+ parallel (>= 1.21.0)
324
+ rbi (~> 0.2)
325
+ sorbet-static-and-runtime (>= 0.5.11087)
326
+ spoom (>= 1.2.0)
327
+ thor (>= 1.2.0)
328
+ yard-sorbet
329
+ thor (1.3.2)
330
+ thread_safe (0.3.6)
331
+ timecop (0.9.10)
332
+ timeout (0.4.3)
333
+ tzinfo (2.0.6)
334
+ concurrent-ruby (~> 1.0)
335
+ unicode-display_width (2.6.0)
336
+ unparser (0.8.0)
337
+ diff-lcs (~> 1.6)
338
+ parser (>= 3.3.0)
339
+ prism (>= 1.4)
340
+ uri (1.0.3)
341
+ useragent (0.16.11)
342
+ webmock (3.24.0)
343
+ addressable (>= 2.8.0)
344
+ crack (>= 0.3.2)
345
+ hashdiff (>= 0.4.0, < 2.0.0)
346
+ yard (0.9.37)
347
+ yard-sorbet (0.9.0)
348
+ sorbet-runtime
349
+ yard
350
+ zeitwerk (2.7.1)
351
+
352
+ PLATFORMS
353
+ aarch64-linux-gnu
354
+ aarch64-linux-musl
355
+ arm64-darwin
356
+ x86_64-darwin
357
+ x86_64-linux-gnu
358
+ x86_64-linux-musl
359
+
360
+ DEPENDENCIES
361
+ activemodel
362
+ activerecord (~> 8.0.0)
363
+ activesupport (~> 8.0.0)
364
+ alchemrest!
365
+ appraisal
366
+ betterlint
367
+ combustion
368
+ factory_bot
369
+ faraday (~> 1.10)
370
+ moneta
371
+ mutant-rspec (~> 0.13.4)
372
+ pg
373
+ pry
374
+ rake (~> 13.0)
375
+ rspec (~> 3.0)
376
+ rspec_junit_formatter
377
+ rubocop
378
+ rubocop-rspec
379
+ sorbet
380
+ tapioca (>= 0.16.6)
381
+ timecop
382
+ webmock
383
+
384
+ BUNDLED WITH
385
+ 2.6.9
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Alchemrest
4
+ class CircuitBreaker
5
+ extend Memosa
6
+ include Anima.new(
7
+ :service_name,
8
+ :sleep_window,
9
+ :time_window,
10
+ :error_threshold,
11
+ :volume_threshold,
12
+ :disabled_when,
13
+ )
14
+
15
+ class RequestFailed < StandardError; end
16
+
17
+ DEFAULTS = {
18
+ # number of seconds the circuit stays open once we pass the error threshold
19
+ sleep_window: 90,
20
+ # length of interval (in seconds) over which it calculates the error rate
21
+ time_window: 60,
22
+ # number of requests within `time_window` seconds before it calculates
23
+ # error rates (checked on failures)
24
+ volume_threshold: 5,
25
+ # exceeding this rate will open the circuit (checked on failures)
26
+ error_threshold: 50,
27
+ disabled_when: nil,
28
+ }.freeze
29
+
30
+ def initialize(args)
31
+ super(**DEFAULTS, **args)
32
+ end
33
+
34
+ def enabled?
35
+ !service_name.nil? && (disabled_when.nil? || !disabled_when.call)
36
+ end
37
+
38
+ def open?
39
+ enabled? && circuit_box.open?
40
+ end
41
+
42
+ def monitor!(result:)
43
+ return unless enabled?
44
+
45
+ outcome = circuit_box.run(exception: false) do
46
+ raise RequestFailed if request_failed?(result:)
47
+
48
+ :success
49
+ end
50
+
51
+ outcome || :failure
52
+ end
53
+
54
+ private
55
+
56
+ def request_failed?(result:)
57
+ case result
58
+ in Alchemrest::Result::Error(Alchemrest::ServerError | Alchemrest::RequestFailedError)
59
+ true
60
+ else
61
+ false
62
+ end
63
+ end
64
+
65
+ memoize def circuit_box
66
+ Circuitbox.circuit(service_name, circuit_box_options)
67
+ end
68
+
69
+ def circuit_box_options
70
+ {
71
+ # number of seconds the circuit stays open once we pass the error threshold
72
+ sleep_window:,
73
+ # length of interval (in seconds) over which it calculates the error rate
74
+ time_window:,
75
+ # number of requests within `time_window` seconds before it calculates
76
+ # error rates (checked on failures)
77
+ volume_threshold:,
78
+ # exceeding this rate will open the circuit (checked on failures)
79
+ error_threshold:,
80
+ exceptions: [RequestFailed],
81
+ }
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "faraday/request/json"
4
+
5
+ module Alchemrest
6
+ class Client
7
+ class Configuration
8
+ class Connection
9
+ attr_accessor :url, :headers, :customize_block
10
+ attr_reader :client_configuration, :use_default_middleware
11
+
12
+ def initialize(client_configuration)
13
+ @client_configuration = client_configuration
14
+ @use_default_middleware = true
15
+ end
16
+
17
+ def customize(use_default_middleware: true, &block)
18
+ @use_default_middleware = use_default_middleware
19
+ self.customize_block = block
20
+ end
21
+
22
+ def create_new_connection
23
+ unless frozen?
24
+ raise ConfigurationNotReadyError, "Don't use configuration to build connections until the configuration has been frozen"
25
+ end
26
+
27
+ Faraday.new(url: url, headers: headers) do |c|
28
+ c.use Faraday::Request::Json
29
+
30
+ apply_configuration(c)
31
+ end
32
+ end
33
+
34
+ def freeze
35
+ validate!
36
+ super
37
+ end
38
+
39
+ private
40
+
41
+ def use_default_middleware?
42
+ @use_default_middleware
43
+ end
44
+
45
+ def use_kill_switch?
46
+ client_configuration.kill_switch_enabled?
47
+ end
48
+
49
+ def underscore_response_body_keys?
50
+ client_configuration.underscore_response_body_keys
51
+ end
52
+
53
+ def kill_switch_adapter_ready?
54
+ Alchemrest.kill_switch_adapter.ready?
55
+ end
56
+
57
+ def validate!
58
+ raise InvalidConfigurationError, "No url provided" if url.blank?
59
+ end
60
+
61
+ def apply_configuration(connection)
62
+ customize_block.call(connection) if customize_block
63
+ apply_middleware(connection)
64
+ end
65
+
66
+ def apply_middleware(connection)
67
+ if use_default_middleware?
68
+ if client_configuration.service_name
69
+ if use_kill_switch? && kill_switch_adapter_ready?
70
+ connection.use FaradayMiddleware::KillSwitch, service_name: client_configuration.service_name
71
+ end
72
+
73
+ connection.use FaradayMiddleware::ExternalApiInstrumentation, external_service: client_configuration.service_name
74
+ end
75
+
76
+ connection.use FaradayMiddleware::UnderScoreResponse if underscore_response_body_keys?
77
+ connection.use FaradayMiddleware::JsonParser
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Alchemrest
4
+ class Client
5
+ class Configuration
6
+ attr_accessor :service_name,
7
+ :underscore_response_body_keys
8
+
9
+ attr_reader :circuit_breaker,
10
+ :kill_switch_enabled
11
+
12
+ def kill_switch_enabled? = kill_switch_enabled
13
+
14
+ def initialize
15
+ @underscore_response_body_keys = true
16
+ end
17
+
18
+ def connection
19
+ @connection ||= Connection.new(self)
20
+ end
21
+
22
+ def freeze
23
+ connection.freeze
24
+
25
+ # enable defaults if they haven't been explicitly configured
26
+ unless circuit_breaker
27
+ use_circuit_breaker
28
+ end
29
+
30
+ if kill_switch_enabled.nil?
31
+ use_kill_switch
32
+ end
33
+
34
+ super()
35
+ end
36
+
37
+ def ready?
38
+ frozen?
39
+ end
40
+
41
+ def use_circuit_breaker(circuit_breaker_option = nil)
42
+ ensure_service_name!
43
+ raise InvalidConfigurationError, "already called `use_circuit_breaker`" unless circuit_breaker.nil?
44
+
45
+ @circuit_breaker = case circuit_breaker_option
46
+ in CircuitBreaker
47
+ circuit_breaker_option
48
+ in Hash => options
49
+ build_default_circuit_breaker(**options)
50
+ in true | nil
51
+ build_default_circuit_breaker
52
+ in false
53
+ build_default_circuit_breaker(disabled_when: -> { true })
54
+ end
55
+ end
56
+
57
+ def use_kill_switch(value = true) # rubocop:disable Style/OptionalBooleanParameter
58
+ ensure_service_name!
59
+ raise InvalidConfigurationError, "already called `use_kill_switch`" unless kill_switch_enabled.nil?
60
+
61
+ @kill_switch_enabled = value
62
+ end
63
+
64
+ private
65
+
66
+ def ensure_service_name!
67
+ return if service_name
68
+
69
+ unless connection.url
70
+ raise InvalidConfigurationError,
71
+ "You must set `config.service_name` or `config.connection.url` before trying to use circuit breakers or kill switches"
72
+ end
73
+
74
+ @service_name = default_service_name
75
+ end
76
+
77
+ def default_service_name
78
+ URI(connection.url).hostname
79
+ end
80
+
81
+ def build_default_circuit_breaker(options = {})
82
+ CircuitBreaker.new(
83
+ service_name:,
84
+ **options,
85
+ )
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Alchemrest
4
+ class Client
5
+ def self.inherited(subclass) # rubocop:disable Lint/MissingSuper
6
+ subclass.class_eval do
7
+ def connection
8
+ self.class.connection
9
+ end
10
+
11
+ def self.connection
12
+ @connection ||= configuration.connection.create_new_connection
13
+ end
14
+ end
15
+ end
16
+
17
+ def self.configuration
18
+ raise InvalidConfigurationError, "Call `configure` in your client class to setup connection details" unless @configuration
19
+
20
+ @configuration
21
+ end
22
+
23
+ def self.configure(&configuration_block)
24
+ @configuration = begin
25
+ config = Alchemrest::Client::Configuration.new
26
+ class_exec(config, &configuration_block)
27
+ config.freeze
28
+ config
29
+ end
30
+ end
31
+
32
+ def self.kill_switch
33
+ KillSwitch.new(service_name: configuration.service_name)
34
+ end
35
+
36
+ def configuration
37
+ self.class.configuration
38
+ end
39
+
40
+ def build_http_request(request)
41
+ HttpRequest.new(request, self)
42
+ end
43
+
44
+ def build_response(raw_response)
45
+ Response.new(raw_response)
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop'
4
+
5
+ require_relative '../rubocop/cop/alchemrest/request_hash_returning_block'
6
+ require_relative '../rubocop/cop/alchemrest/define_request_using_with_params'
7
+ require_relative '../rubocop/cop/alchemrest/endpoint_definition_using_generic_params'
8
+ require_relative '../rubocop/cop/alchemrest/time_transform_with_no_zone'