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.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +22 -0
- data/.rubocop_todo.yml +242 -0
- data/.ruby-version +1 -0
- data/Appraisals +19 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +378 -0
- data/Rakefile +29 -0
- data/alchemrest.gemspec +71 -0
- data/coach.yml +5 -0
- data/examples/bank_api/client.rb +31 -0
- data/examples/bank_api/data/account.rb +21 -0
- data/examples/bank_api/data/ach.rb +16 -0
- data/examples/bank_api/data/business_account.rb +22 -0
- data/examples/bank_api/data/card.rb +21 -0
- data/examples/bank_api/data/check.rb +19 -0
- data/examples/bank_api/data/product.rb +20 -0
- data/examples/bank_api/data/transaction.rb +49 -0
- data/examples/bank_api/data/user.rb +27 -0
- data/examples/bank_api/factories.rb +68 -0
- data/examples/bank_api/graph_visualization.rb +45 -0
- data/examples/bank_api/positive_interest_string.rb +33 -0
- data/examples/bank_api/requests/delete_user.rb +17 -0
- data/examples/bank_api/requests/get_business_account.rb +24 -0
- data/examples/bank_api/requests/get_products.rb +12 -0
- data/examples/bank_api/requests/get_transactions.rb +34 -0
- data/examples/bank_api/requests/get_user.rb +19 -0
- data/examples/bank_api/requests/post_transaction.rb +20 -0
- data/examples/bank_api/requests/update_user.rb +28 -0
- data/examples/bank_api/root.rb +52 -0
- data/examples/bank_api.rb +33 -0
- data/gemfiles/faraday_2.gemfile +9 -0
- data/gemfiles/faraday_2.gemfile.lock +363 -0
- data/gemfiles/rails_7_0.gemfile.lock +341 -0
- data/gemfiles/rails_7_2.gemfile +9 -0
- data/gemfiles/rails_7_2.gemfile.lock +384 -0
- data/gemfiles/rails_8_0.gemfile +9 -0
- data/gemfiles/rails_8_0.gemfile.lock +385 -0
- data/lib/alchemrest/circuit_breaker.rb +84 -0
- data/lib/alchemrest/client/configuration/connection.rb +83 -0
- data/lib/alchemrest/client/configuration.rb +89 -0
- data/lib/alchemrest/client.rb +48 -0
- data/lib/alchemrest/cop.rb +8 -0
- data/lib/alchemrest/data/capture_configuration.rb +77 -0
- data/lib/alchemrest/data/field.rb +36 -0
- data/lib/alchemrest/data/graph.rb +40 -0
- data/lib/alchemrest/data/record.rb +60 -0
- data/lib/alchemrest/data/schema.rb +80 -0
- data/lib/alchemrest/data.rb +9 -0
- data/lib/alchemrest/endpoint_definition.rb +47 -0
- data/lib/alchemrest/error.rb +122 -0
- data/lib/alchemrest/factory_bot.rb +64 -0
- data/lib/alchemrest/faraday_middleware/external_api_instrumentation.rb +24 -0
- data/lib/alchemrest/faraday_middleware/json_parser.rb +30 -0
- data/lib/alchemrest/faraday_middleware/kill_switch.rb +22 -0
- data/lib/alchemrest/faraday_middleware/underscore_response.rb +24 -0
- data/lib/alchemrest/hash_path.rb +81 -0
- data/lib/alchemrest/http_request.rb +75 -0
- data/lib/alchemrest/kill_switch/adapters.rb +88 -0
- data/lib/alchemrest/kill_switch.rb +31 -0
- data/lib/alchemrest/railtie.rb +25 -0
- data/lib/alchemrest/request/endpoint.rb +29 -0
- data/lib/alchemrest/request/returns.rb +46 -0
- data/lib/alchemrest/request.rb +80 -0
- data/lib/alchemrest/request_definition/builder.rb +13 -0
- data/lib/alchemrest/request_definition.rb +26 -0
- data/lib/alchemrest/response/pipeline/extract_payload.rb +64 -0
- data/lib/alchemrest/response/pipeline/final.rb +11 -0
- data/lib/alchemrest/response/pipeline/omit.rb +46 -0
- data/lib/alchemrest/response/pipeline/sanitize.rb +59 -0
- data/lib/alchemrest/response/pipeline/transform.rb +26 -0
- data/lib/alchemrest/response/pipeline/was_successful.rb +29 -0
- data/lib/alchemrest/response/pipeline.rb +71 -0
- data/lib/alchemrest/response.rb +73 -0
- data/lib/alchemrest/response_captured_handler.rb +68 -0
- data/lib/alchemrest/result/halt.rb +15 -0
- data/lib/alchemrest/result/try_helpers.rb +16 -0
- data/lib/alchemrest/result.rb +128 -0
- data/lib/alchemrest/root.rb +77 -0
- data/lib/alchemrest/transforms/base_to_type_transform_registry.rb +42 -0
- data/lib/alchemrest/transforms/constrainable.rb +41 -0
- data/lib/alchemrest/transforms/constraint/block.rb +22 -0
- data/lib/alchemrest/transforms/constraint/greater_than.rb +19 -0
- data/lib/alchemrest/transforms/constraint/greater_than_or_eq.rb +19 -0
- data/lib/alchemrest/transforms/constraint/in_list.rb +19 -0
- data/lib/alchemrest/transforms/constraint/is_instance_of.rb +19 -0
- data/lib/alchemrest/transforms/constraint/is_uuid.rb +19 -0
- data/lib/alchemrest/transforms/constraint/less_than.rb +19 -0
- data/lib/alchemrest/transforms/constraint/less_than_or_eq.rb +19 -0
- data/lib/alchemrest/transforms/constraint/matches_regex.rb +19 -0
- data/lib/alchemrest/transforms/constraint/max_length.rb +19 -0
- data/lib/alchemrest/transforms/constraint/min_length.rb +19 -0
- data/lib/alchemrest/transforms/constraint.rb +17 -0
- data/lib/alchemrest/transforms/constraint_builder/for_number.rb +25 -0
- data/lib/alchemrest/transforms/constraint_builder/for_string.rb +21 -0
- data/lib/alchemrest/transforms/constraint_builder.rb +15 -0
- data/lib/alchemrest/transforms/date_transform.rb +30 -0
- data/lib/alchemrest/transforms/enum.rb +52 -0
- data/lib/alchemrest/transforms/epoch_time.rb +32 -0
- data/lib/alchemrest/transforms/from_chain.rb +15 -0
- data/lib/alchemrest/transforms/from_number/to_type_transform_registry.rb +18 -0
- data/lib/alchemrest/transforms/from_number.rb +47 -0
- data/lib/alchemrest/transforms/from_string/to_type_transform_registry.rb +17 -0
- data/lib/alchemrest/transforms/from_string.rb +36 -0
- data/lib/alchemrest/transforms/from_type/empty_to_type_transform_registry.rb +14 -0
- data/lib/alchemrest/transforms/from_type.rb +64 -0
- data/lib/alchemrest/transforms/iso_time.rb +58 -0
- data/lib/alchemrest/transforms/json_number.rb +26 -0
- data/lib/alchemrest/transforms/loose_hash.rb +96 -0
- data/lib/alchemrest/transforms/money_transform.rb +42 -0
- data/lib/alchemrest/transforms/number.rb +27 -0
- data/lib/alchemrest/transforms/output_type.rb +65 -0
- data/lib/alchemrest/transforms/to_decimal.rb +22 -0
- data/lib/alchemrest/transforms/to_type/from_string_to_time_selector.rb +29 -0
- data/lib/alchemrest/transforms/to_type/transforms_selector.rb +61 -0
- data/lib/alchemrest/transforms/to_type.rb +86 -0
- data/lib/alchemrest/transforms/typed.rb +32 -0
- data/lib/alchemrest/transforms/union.rb +44 -0
- data/lib/alchemrest/transforms/with_constraint.rb +26 -0
- data/lib/alchemrest/transforms.rb +93 -0
- data/lib/alchemrest/url_builder/encoders.rb +39 -0
- data/lib/alchemrest/url_builder/options.rb +33 -0
- data/lib/alchemrest/url_builder.rb +31 -0
- data/lib/alchemrest/version.rb +5 -0
- data/lib/alchemrest/webmock_helpers.rb +27 -0
- data/lib/alchemrest.rb +159 -0
- data/lib/generators/alchemrest/kill_switch_migration_generator.rb +27 -0
- data/lib/generators/alchemrest/templates/kill_switch_migration.rb.erb +17 -0
- data/lib/rubocop/cop/alchemrest/define_request_using_with_params.rb +53 -0
- data/lib/rubocop/cop/alchemrest/endpoint_definition_using_generic_params.rb +55 -0
- data/lib/rubocop/cop/alchemrest/request_hash_returning_block.rb +54 -0
- data/lib/rubocop/cop/alchemrest/time_transform_with_no_zone.rb +56 -0
- data/lib/tapioca/dsl/compilers/alchemrest_data.rb +84 -0
- data/lib/tapioca/dsl/compilers/alchemrest_root.rb +68 -0
- data/mutant.yml +16 -0
- data/rbi/alchemrest/result.rbi +80 -0
- data/rbi/alchemrest.rbi +246 -0
- data/sorbet/config +5 -0
- data/sorbet/rbi/gems/.gitattributes +1 -0
- data/sorbet/rbi/gems/abstract_type@0.0.7.rbi +41 -0
- data/sorbet/rbi/gems/actionpack@8.0.4.rbi +11733 -0
- data/sorbet/rbi/gems/actionview@8.0.4.rbi +6560 -0
- data/sorbet/rbi/gems/activemodel@8.0.4.rbi +2891 -0
- data/sorbet/rbi/gems/activesupport@8.0.4.rbi +9621 -0
- data/sorbet/rbi/gems/adamantium@0.2.0.rbi +144 -0
- data/sorbet/rbi/gems/addressable@2.8.7.rbi +779 -0
- data/sorbet/rbi/gems/anima@0.3.2.rbi +103 -0
- data/sorbet/rbi/gems/ast@2.4.2.rbi +107 -0
- data/sorbet/rbi/gems/base64@0.3.0.rbi +52 -0
- data/sorbet/rbi/gems/benchmark@0.5.0.rbi +153 -0
- data/sorbet/rbi/gems/bigdecimal@3.3.1.rbi +77 -0
- data/sorbet/rbi/gems/builder@3.3.0.rbi +9 -0
- data/sorbet/rbi/gems/circuitbox@2.0.0.rbi +297 -0
- data/sorbet/rbi/gems/concord@0.1.6.rbi +51 -0
- data/sorbet/rbi/gems/concurrent-ruby@1.3.5.rbi +4716 -0
- data/sorbet/rbi/gems/connection_pool@2.5.4.rbi +9 -0
- data/sorbet/rbi/gems/crack@1.0.0.rbi +110 -0
- data/sorbet/rbi/gems/crass@1.0.6.rbi +294 -0
- data/sorbet/rbi/gems/date@3.4.1.rbi +58 -0
- data/sorbet/rbi/gems/drb@2.2.3.rbi +639 -0
- data/sorbet/rbi/gems/equalizer@0.0.11.rbi +38 -0
- data/sorbet/rbi/gems/erubi@1.13.1.rbi +85 -0
- data/sorbet/rbi/gems/factory_bot@6.5.0.rbi +1529 -0
- data/sorbet/rbi/gems/faraday-em_http@1.0.0.rbi +181 -0
- data/sorbet/rbi/gems/faraday-em_synchrony@1.0.1.rbi +120 -0
- data/sorbet/rbi/gems/faraday-excon@1.1.0.rbi +128 -0
- data/sorbet/rbi/gems/faraday-httpclient@1.0.1.rbi +123 -0
- data/sorbet/rbi/gems/faraday-multipart@1.2.0.rbi +190 -0
- data/sorbet/rbi/gems/faraday-net_http@1.0.2.rbi +140 -0
- data/sorbet/rbi/gems/faraday-net_http_persistent@1.2.0.rbi +116 -0
- data/sorbet/rbi/gems/faraday-patron@1.0.0.rbi +119 -0
- data/sorbet/rbi/gems/faraday-rack@1.0.0.rbi +113 -0
- data/sorbet/rbi/gems/faraday-retry@1.0.3.rbi +149 -0
- data/sorbet/rbi/gems/faraday@1.10.5.rbi +1620 -0
- data/sorbet/rbi/gems/hansi@0.2.1.rbi +9 -0
- data/sorbet/rbi/gems/hashdiff@1.1.2.rbi +174 -0
- data/sorbet/rbi/gems/i18n@1.14.7.rbi +1328 -0
- data/sorbet/rbi/gems/ice_nine@0.11.2.rbi +145 -0
- data/sorbet/rbi/gems/io-console@0.8.0.rbi +9 -0
- data/sorbet/rbi/gems/json@2.9.1.rbi +282 -0
- data/sorbet/rbi/gems/language_server-protocol@3.17.0.3.rbi +8057 -0
- data/sorbet/rbi/gems/logger@1.7.0.rbi +260 -0
- data/sorbet/rbi/gems/loofah@2.24.0.rbi +571 -0
- data/sorbet/rbi/gems/memoizable@0.4.2.rbi +131 -0
- data/sorbet/rbi/gems/memosa@0.8.2.rbi +185 -0
- data/sorbet/rbi/gems/minitest@5.26.0.rbi +824 -0
- data/sorbet/rbi/gems/money@6.19.0.rbi +815 -0
- data/sorbet/rbi/gems/morpher@0.4.2.rbi +388 -0
- data/sorbet/rbi/gems/mprelude@0.1.0.rbi +140 -0
- data/sorbet/rbi/gems/multi_json@1.15.0.rbi +180 -0
- data/sorbet/rbi/gems/multipart-post@2.4.1.rbi +154 -0
- data/sorbet/rbi/gems/mustermann-contrib@3.0.3.rbi +9 -0
- data/sorbet/rbi/gems/mustermann@3.0.3.rbi +809 -0
- data/sorbet/rbi/gems/netrc@0.11.0.rbi +112 -0
- data/sorbet/rbi/gems/nokogiri@1.19.1.rbi +3412 -0
- data/sorbet/rbi/gems/parallel@1.26.3.rbi +234 -0
- data/sorbet/rbi/gems/parser@3.3.7.0.rbi +4877 -0
- data/sorbet/rbi/gems/pp@0.6.2.rbi +176 -0
- data/sorbet/rbi/gems/prettyprint@0.2.0.rbi +155 -0
- data/sorbet/rbi/gems/prism@1.5.1.rbi +26368 -0
- data/sorbet/rbi/gems/procto@0.0.3.rbi +9 -0
- data/sorbet/rbi/gems/psych@5.2.3.rbi +806 -0
- data/sorbet/rbi/gems/public_suffix@6.0.1.rbi +267 -0
- data/sorbet/rbi/gems/racc@1.8.1.rbi +120 -0
- data/sorbet/rbi/gems/rack-session@2.1.1.rbi +458 -0
- data/sorbet/rbi/gems/rack-test@2.2.0.rbi +405 -0
- data/sorbet/rbi/gems/rack@3.1.14.rbi +2774 -0
- data/sorbet/rbi/gems/rackup@2.2.1.rbi +132 -0
- data/sorbet/rbi/gems/rails-dom-testing@2.2.0.rbi +266 -0
- data/sorbet/rbi/gems/rails-html-sanitizer@1.6.2.rbi +545 -0
- data/sorbet/rbi/gems/railties@8.0.4.rbi +2150 -0
- data/sorbet/rbi/gems/rainbow@3.1.1.rbi +333 -0
- data/sorbet/rbi/gems/rake@13.2.1.rbi +2054 -0
- data/sorbet/rbi/gems/rbi@0.2.3.rbi +3961 -0
- data/sorbet/rbi/gems/rdoc@6.13.1.rbi +6784 -0
- data/sorbet/rbi/gems/regexp_parser@2.11.3.rbi +3020 -0
- data/sorbet/rbi/gems/reline@0.6.0.rbi +9 -0
- data/sorbet/rbi/gems/rexml@3.4.2.rbi +1777 -0
- data/sorbet/rbi/gems/rubocop-ast@1.38.0.rbi +5293 -0
- data/sorbet/rbi/gems/rubocop@1.71.1.rbi +31846 -0
- data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +980 -0
- data/sorbet/rbi/gems/ruby2_keywords@0.0.5.rbi +9 -0
- data/sorbet/rbi/gems/securerandom@0.4.1.rbi +33 -0
- data/sorbet/rbi/gems/sentry-ruby@5.22.1.rbi +3782 -0
- data/sorbet/rbi/gems/spoom@1.5.1.rbi +4321 -0
- data/sorbet/rbi/gems/stringio@3.1.2.rbi +9 -0
- data/sorbet/rbi/gems/tapioca@0.16.8.rbi +3399 -0
- data/sorbet/rbi/gems/thor@1.3.2.rbi +2012 -0
- data/sorbet/rbi/gems/thread_safe@0.3.6.rbi +711 -0
- data/sorbet/rbi/gems/timeout@0.4.4.rbi +80 -0
- data/sorbet/rbi/gems/tsort@0.2.0.rbi +50 -0
- data/sorbet/rbi/gems/tzinfo@2.0.6.rbi +1677 -0
- data/sorbet/rbi/gems/unicode-display_width@2.6.0.rbi +62 -0
- data/sorbet/rbi/gems/uri@1.1.0.rbi +760 -0
- data/sorbet/rbi/gems/useragent@0.16.11.rbi +9 -0
- data/sorbet/rbi/gems/webmock@3.24.0.rbi +1362 -0
- data/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +345 -0
- data/sorbet/rbi/gems/yard@0.9.37.rbi +8795 -0
- data/sorbet/rbi/gems/zeitwerk@2.7.1.rbi +589 -0
- data/sorbet/tapioca/config.yml +45 -0
- data/sorbet/tapioca/require.rb +8 -0
- data/sorbet/tapioca/sorbet/rbi/dsl/.gitattributes +1 -0
- data/sorbet/tapioca/sorbet/rbi/dsl/active_support/callbacks.rbi +23 -0
- metadata +737 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Alchemrest
|
|
5
|
+
class UrlBuilder
|
|
6
|
+
class Options
|
|
7
|
+
attr_accessor :values, :query
|
|
8
|
+
|
|
9
|
+
attr_reader :query_param_encoder
|
|
10
|
+
|
|
11
|
+
InvalidEncoderError = Class.new(StandardError)
|
|
12
|
+
|
|
13
|
+
def encode_query_with=(name)
|
|
14
|
+
@query_param_encoder = Encoders.find(name)
|
|
15
|
+
rescue NoMatchingPatternError
|
|
16
|
+
raise InvalidEncoderError, ":#{name} is not a known query string encoder type. Known types are :rack and :form"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def encode_query_with(&)
|
|
20
|
+
@query_param_encoder = Encoders::Custom.new(&)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def create_builder(template:)
|
|
24
|
+
UrlBuilder.new(
|
|
25
|
+
template:,
|
|
26
|
+
query: query,
|
|
27
|
+
values: values,
|
|
28
|
+
query_param_encoder: query_param_encoder,
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Alchemrest
|
|
5
|
+
class UrlBuilder
|
|
6
|
+
include Anima.new(:template, :query_param_encoder, :values, :query)
|
|
7
|
+
|
|
8
|
+
def initialize(args)
|
|
9
|
+
super({ values: nil, query: nil, query_param_encoder: Encoders.find(:form) }.merge(**args.compact))
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def url
|
|
13
|
+
base = values ? Mustermann::Expander.new(template).expand(values) : template
|
|
14
|
+
|
|
15
|
+
if query_string
|
|
16
|
+
"#{base}?#{query_string}"
|
|
17
|
+
else
|
|
18
|
+
base
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def query_string
|
|
25
|
+
return nil unless query
|
|
26
|
+
return nil if query.compact.empty?
|
|
27
|
+
|
|
28
|
+
query_param_encoder.call(query.compact)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Alchemrest
|
|
4
|
+
module WebmockHelpers
|
|
5
|
+
module_function def stub_alchemrest_request(alchemrest_request, with_request_body: false, with_headers: false)
|
|
6
|
+
stub_url = if defined?(alchemrest_request.url)
|
|
7
|
+
alchemrest_request.url
|
|
8
|
+
else
|
|
9
|
+
Addressable::Template.new("http://{host}#{alchemrest_request.path}")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
http_method = alchemrest_request.http_method.to_sym
|
|
13
|
+
|
|
14
|
+
stub = if with_request_body
|
|
15
|
+
stub_request(http_method, stub_url).with(body: alchemrest_request.body)
|
|
16
|
+
else
|
|
17
|
+
stub_request(http_method, stub_url)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
if with_headers
|
|
21
|
+
stub.with(headers: alchemrest_request.headers)
|
|
22
|
+
else
|
|
23
|
+
stub
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
data/lib/alchemrest.rb
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "morpher"
|
|
4
|
+
require "money"
|
|
5
|
+
require 'faraday'
|
|
6
|
+
require 'multi_json'
|
|
7
|
+
require "active_support"
|
|
8
|
+
require "active_support/core_ext/hash"
|
|
9
|
+
require "active_support/core_ext/object"
|
|
10
|
+
require "active_support/parameter_filter"
|
|
11
|
+
require "active_support/hash_with_indifferent_access"
|
|
12
|
+
require "circuitbox"
|
|
13
|
+
require 'sorbet-runtime'
|
|
14
|
+
require "rack/utils"
|
|
15
|
+
require_relative "alchemrest/version"
|
|
16
|
+
require_relative "alchemrest/hash_path"
|
|
17
|
+
require_relative "alchemrest/transforms"
|
|
18
|
+
require_relative "alchemrest/transforms/constrainable"
|
|
19
|
+
require_relative "alchemrest/transforms/from_type"
|
|
20
|
+
require_relative "alchemrest/transforms/to_type"
|
|
21
|
+
require_relative "alchemrest/transforms/to_type/transforms_selector"
|
|
22
|
+
require_relative "alchemrest/transforms/constraint"
|
|
23
|
+
require_relative "alchemrest/transforms/constraint_builder"
|
|
24
|
+
require_relative "alchemrest/transforms/constraint_builder/for_string"
|
|
25
|
+
require_relative "alchemrest/transforms/constraint_builder/for_number"
|
|
26
|
+
require_relative "alchemrest/transforms/constraint/block"
|
|
27
|
+
require_relative "alchemrest/transforms/with_constraint"
|
|
28
|
+
require_relative "alchemrest/data/field"
|
|
29
|
+
require_relative "alchemrest/data/graph"
|
|
30
|
+
require_relative "alchemrest/data/capture_configuration"
|
|
31
|
+
require_relative "alchemrest/data/record"
|
|
32
|
+
require_relative "alchemrest/data/schema"
|
|
33
|
+
require_relative "alchemrest/data"
|
|
34
|
+
require_relative "alchemrest/transforms/base_to_type_transform_registry"
|
|
35
|
+
require_relative "alchemrest/transforms/from_type/empty_to_type_transform_registry"
|
|
36
|
+
|
|
37
|
+
Dir.glob(File.join(__dir__, 'alchemrest', 'transforms', '*.rb')).each do |file|
|
|
38
|
+
require_relative file
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
require_relative "alchemrest/transforms/constraint/matches_regex"
|
|
42
|
+
Dir.glob(File.join(__dir__, 'alchemrest', 'transforms', 'constraint', '*.rb')).each do |file|
|
|
43
|
+
require_relative file
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
require_relative "alchemrest/transforms/to_type/from_string_to_time_selector"
|
|
47
|
+
require_relative "alchemrest/transforms/from_string/to_type_transform_registry"
|
|
48
|
+
require_relative "alchemrest/transforms/from_number/to_type_transform_registry"
|
|
49
|
+
require_relative "alchemrest/result"
|
|
50
|
+
require_relative 'alchemrest/result/halt'
|
|
51
|
+
require_relative 'alchemrest/result/try_helpers'
|
|
52
|
+
require_relative "alchemrest/error"
|
|
53
|
+
require_relative "alchemrest/response"
|
|
54
|
+
require_relative "alchemrest/response/pipeline"
|
|
55
|
+
require_relative "alchemrest/response/pipeline/transform"
|
|
56
|
+
require_relative "alchemrest/response/pipeline/was_successful"
|
|
57
|
+
require_relative "alchemrest/response/pipeline/final"
|
|
58
|
+
require_relative "alchemrest/response/pipeline/extract_payload"
|
|
59
|
+
require_relative "alchemrest/response/pipeline/sanitize"
|
|
60
|
+
require_relative "alchemrest/response/pipeline/omit"
|
|
61
|
+
require_relative "alchemrest/response_captured_handler"
|
|
62
|
+
require_relative "alchemrest/client/configuration/connection"
|
|
63
|
+
require_relative "alchemrest/client/configuration"
|
|
64
|
+
require_relative "alchemrest/client"
|
|
65
|
+
require_relative "alchemrest/url_builder"
|
|
66
|
+
require_relative "alchemrest/url_builder/encoders"
|
|
67
|
+
require_relative "alchemrest/url_builder/options"
|
|
68
|
+
require_relative "alchemrest/endpoint_definition"
|
|
69
|
+
require_relative "alchemrest/request/endpoint"
|
|
70
|
+
require_relative "alchemrest/request/returns"
|
|
71
|
+
require_relative "alchemrest/request"
|
|
72
|
+
require_relative "alchemrest/request_definition"
|
|
73
|
+
require_relative "alchemrest/request_definition/builder"
|
|
74
|
+
require_relative "alchemrest/root"
|
|
75
|
+
require_relative "alchemrest/kill_switch"
|
|
76
|
+
require_relative "alchemrest/kill_switch/adapters"
|
|
77
|
+
require_relative "alchemrest/circuit_breaker"
|
|
78
|
+
require_relative "alchemrest/http_request"
|
|
79
|
+
require_relative "alchemrest/faraday_middleware/json_parser"
|
|
80
|
+
require_relative "alchemrest/faraday_middleware/underscore_response"
|
|
81
|
+
require_relative "alchemrest/faraday_middleware/external_api_instrumentation"
|
|
82
|
+
require_relative "alchemrest/faraday_middleware/kill_switch"
|
|
83
|
+
require_relative "alchemrest/webmock_helpers"
|
|
84
|
+
require_relative "alchemrest/factory_bot"
|
|
85
|
+
require_relative "alchemrest/railtie"
|
|
86
|
+
|
|
87
|
+
module Alchemrest
|
|
88
|
+
DEFAULT_RESCUABLE_EXCEPTIONS = [Alchemrest::Error].freeze
|
|
89
|
+
|
|
90
|
+
DEFAULT_FILTER_PARAMETERS = %i(ssn password token).freeze
|
|
91
|
+
|
|
92
|
+
@filter_parameters = DEFAULT_FILTER_PARAMETERS
|
|
93
|
+
|
|
94
|
+
def self.logger
|
|
95
|
+
@logger ||= Logger.new($stdout)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def self.logger=(logger)
|
|
99
|
+
@logger = logger
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# mutant:disable
|
|
103
|
+
def self.deprecator
|
|
104
|
+
@deprecator ||= ActiveSupport::Deprecation.new("3.0", "Alchemrest")
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def self.filter_parameters
|
|
108
|
+
@filter_parameters
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def self.filter_parameters=(params)
|
|
112
|
+
@filter_parameters = params.uniq
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def self.parameter_filter
|
|
116
|
+
ActiveSupport::ParameterFilter.new(@filter_parameters)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def self.on_result_rescued(&block)
|
|
120
|
+
@on_result_rescued = block if block
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def self.on_response_captured(&block)
|
|
124
|
+
@on_response_captured = block if block
|
|
125
|
+
@on_response_captured
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def self.restore_default_result_rescue_behavior
|
|
129
|
+
@on_result_rescued = nil
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def self.restore_default_response_capture_behavior
|
|
133
|
+
@on_response_captured = nil
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def self.handle_rescued_result(error)
|
|
137
|
+
if @on_result_rescued
|
|
138
|
+
@on_result_rescued.call(error)
|
|
139
|
+
else
|
|
140
|
+
logger.warn(error.to_s)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def self.rescuable_exceptions
|
|
145
|
+
@rescuable_exceptions || DEFAULT_RESCUABLE_EXCEPTIONS
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def self.rescuable_exceptions=(exceptions)
|
|
149
|
+
@rescuable_exceptions = exceptions
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def self.kill_switch_adapter
|
|
153
|
+
@kill_switch_adapter ||= KillSwitch::Adapters::ActiveRecord.new
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def self.kill_switch_adapter=(adapter)
|
|
157
|
+
@kill_switch_adapter = adapter
|
|
158
|
+
end
|
|
159
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails/generators/migration'
|
|
4
|
+
require 'rails/generators/active_record'
|
|
5
|
+
|
|
6
|
+
module Alchemrest
|
|
7
|
+
class KillSwitchMigrationGenerator < Rails::Generators::Base
|
|
8
|
+
include Rails::Generators::Migration
|
|
9
|
+
|
|
10
|
+
source_paths << File.join(File.dirname(__FILE__), 'templates')
|
|
11
|
+
|
|
12
|
+
def self.next_migration_number(dirname)
|
|
13
|
+
ActiveRecord::Generators::Base.next_migration_number dirname
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def create_migration_file
|
|
17
|
+
migration_template 'kill_switch_migration.rb.erb', "db/migrate/create_alchemrest_kill_switches.rb",
|
|
18
|
+
migration_version:
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def migration_version
|
|
24
|
+
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]" if ActiveRecord::VERSION::MAJOR >= 5
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class CreateAlchemrestKillSwitches < ActiveRecord::Migration<%= migration_version %>
|
|
2
|
+
disable_ddl_transaction!
|
|
3
|
+
|
|
4
|
+
def self.up
|
|
5
|
+
create_table :alchemrest_kill_switches, id: :uuid do |t|
|
|
6
|
+
t.string :service_name, null: false
|
|
7
|
+
t.boolean :enabled, null: false, default: false
|
|
8
|
+
t.timestamps
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
add_index :alchemrest_kill_switches, [:service_name], name: "index_alchemrest_kill_switches_on_service_name", unique: true, algorithm: :concurrently
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.down
|
|
15
|
+
drop_table :alchemrest_kill_switches
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Alchemrest
|
|
6
|
+
class DefineRequestUsingWithParams < RuboCop::Cop::Base
|
|
7
|
+
extend RuboCop::Cop::AutoCorrector
|
|
8
|
+
|
|
9
|
+
MSG = <<~MSG
|
|
10
|
+
Using `with_params` to set defaults for a request is deprecated.
|
|
11
|
+
Instead make your block that takes a `request` argument and call `request.defaults = { <some values> }`
|
|
12
|
+
|
|
13
|
+
BAD:
|
|
14
|
+
```
|
|
15
|
+
define_request :get_users, GetUsers, with_params: -> { { id: user_id } }
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
GOOD:
|
|
19
|
+
```
|
|
20
|
+
define_request :get_users, GetUsers do |request|
|
|
21
|
+
request.defaults = { id: user_id }
|
|
22
|
+
end
|
|
23
|
+
```
|
|
24
|
+
MSG
|
|
25
|
+
|
|
26
|
+
def_node_matcher :on_define_request_with_params_proc_call?, <<~PATTERN
|
|
27
|
+
(send nil? :define_request $(sym _) $(const ...) $(hash (pair (sym :with_params) $(block ...))))
|
|
28
|
+
PATTERN
|
|
29
|
+
|
|
30
|
+
def on_send(node)
|
|
31
|
+
on_define_request_with_params_proc_call?(node) do |method_name, klass, with_params_arg, block_node|
|
|
32
|
+
add_offense(with_params_arg) do |corrector|
|
|
33
|
+
correction = build_autocorrection(method_name, klass, block_node)
|
|
34
|
+
corrector.replace(node, correction) if correction
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def build_autocorrection(method_name, klass, block)
|
|
40
|
+
block_body = block.body
|
|
41
|
+
|
|
42
|
+
params_value = block_body.source
|
|
43
|
+
|
|
44
|
+
<<~CODE.chomp
|
|
45
|
+
define_request #{method_name.source}, #{klass.source} do |request|
|
|
46
|
+
request.defaults = #{params_value}
|
|
47
|
+
end
|
|
48
|
+
CODE
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Alchemrest
|
|
6
|
+
class EndpointDefinitionUsingGenericParams < RuboCop::Cop::Base
|
|
7
|
+
extend RuboCop::Cop::AutoCorrector
|
|
8
|
+
|
|
9
|
+
MSG = <<~MSG
|
|
10
|
+
You are using a generic params hash to build a url, rather than explicitly defining which values in the
|
|
11
|
+
hash should be inserted into the path of the url, vs which are query string params. This is deprecated,
|
|
12
|
+
and you should update your code to use `values=` and `query=` instead.
|
|
13
|
+
|
|
14
|
+
BAD:
|
|
15
|
+
endpoint :get, '/api/v1/users/:id' do |url|
|
|
16
|
+
url.params = { id: @id, includeDetails: true }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
GOOD:
|
|
20
|
+
endpoint :get, '/api/v1/users/:id' do |url|
|
|
21
|
+
url.values = { id: @id }
|
|
22
|
+
url.query = { includeDetails: true }
|
|
23
|
+
end
|
|
24
|
+
MSG
|
|
25
|
+
|
|
26
|
+
def_node_matcher :on_endpoint_call?, <<~PATTERN
|
|
27
|
+
(block (send _ :endpoint ...) (args (arg _)) $_)
|
|
28
|
+
PATTERN
|
|
29
|
+
|
|
30
|
+
def_node_matcher :generic_params_assignment?, <<~PATTERN
|
|
31
|
+
(send (lvar $_) :params= _)
|
|
32
|
+
PATTERN
|
|
33
|
+
|
|
34
|
+
def on_block(node)
|
|
35
|
+
on_endpoint_call?(node) do |block_node|
|
|
36
|
+
if generic_params_assignment?(block_node)
|
|
37
|
+
add_offense(block_node) do |corrector|
|
|
38
|
+
correction = build_autocorrection(block_node)
|
|
39
|
+
corrector.replace(block_node, correction) if correction
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def build_autocorrection(block)
|
|
46
|
+
params_value = block.arguments.first.source
|
|
47
|
+
|
|
48
|
+
<<~CODE.chomp
|
|
49
|
+
url.values = #{params_value}
|
|
50
|
+
CODE
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Alchemrest
|
|
6
|
+
class RequestHashReturningBlock < RuboCop::Cop::Base
|
|
7
|
+
extend RuboCop::Cop::AutoCorrector
|
|
8
|
+
|
|
9
|
+
MSG = <<~MSG
|
|
10
|
+
Returning a hash to set url params is deprecated. Instead make your block take a `url` argument and call `url.params = {...}`
|
|
11
|
+
|
|
12
|
+
BAD:
|
|
13
|
+
```
|
|
14
|
+
endpoint :get, '/api/users/:id', -> { { id: user_id } }
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
GOOD:
|
|
18
|
+
```
|
|
19
|
+
endpoint :get, '/api/users/:id' do |url|
|
|
20
|
+
url.params = { id: user_id }
|
|
21
|
+
end
|
|
22
|
+
```
|
|
23
|
+
MSG
|
|
24
|
+
|
|
25
|
+
def_node_matcher :on_endpoint_params_proc_call?, <<~PATTERN
|
|
26
|
+
(send nil? :endpoint $(sym _) $({str | dstr} ...) $(block ...))
|
|
27
|
+
PATTERN
|
|
28
|
+
|
|
29
|
+
def on_send(node)
|
|
30
|
+
on_endpoint_params_proc_call?(node) do |http_method, url, block_node|
|
|
31
|
+
add_offense(block_node) do |corrector|
|
|
32
|
+
correction = build_autocorrection(http_method, url, block_node)
|
|
33
|
+
corrector.replace(node, correction) if correction
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def build_autocorrection(http_method, url, block)
|
|
39
|
+
block_body = block.body
|
|
40
|
+
|
|
41
|
+
params_value = block_body.source
|
|
42
|
+
|
|
43
|
+
url_string = url.source
|
|
44
|
+
|
|
45
|
+
<<~CODE.chomp
|
|
46
|
+
endpoint :#{http_method.value}, #{url_string} do |url|
|
|
47
|
+
url.params = #{params_value}
|
|
48
|
+
end
|
|
49
|
+
CODE
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Alchemrest
|
|
6
|
+
class TimeTransformWithNoZone < RuboCop::Cop::Base
|
|
7
|
+
extend RuboCop::Cop::AutoCorrector
|
|
8
|
+
|
|
9
|
+
MSG = <<~MSG
|
|
10
|
+
Calling `s.from.string.to(Time)` without specifying the timezone is no longer supported
|
|
11
|
+
|
|
12
|
+
BAD:
|
|
13
|
+
```
|
|
14
|
+
s.from.string.to(Time)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
GOOD:
|
|
18
|
+
```
|
|
19
|
+
s.from.string.to(Time).using(:utc)
|
|
20
|
+
s.from.string.to(Time).using(:local)
|
|
21
|
+
s.from.string.to(Time).using(ActiveSupport::TimeZone['Mountain Time (US & Canada)'])
|
|
22
|
+
```
|
|
23
|
+
MSG
|
|
24
|
+
|
|
25
|
+
def_node_matcher :on_time_transform?, <<~PATTERN
|
|
26
|
+
(send (send (send ... :from) :string) :to (const nil? :Time))
|
|
27
|
+
PATTERN
|
|
28
|
+
|
|
29
|
+
def_node_matcher :on_good_time_transform?, <<~PATTERN
|
|
30
|
+
(send (send (send (send ... :from) :string) :to (const nil? :Time)) :using ...)
|
|
31
|
+
PATTERN
|
|
32
|
+
|
|
33
|
+
def on_hash(node)
|
|
34
|
+
node.pairs.each do |pair|
|
|
35
|
+
transform_node = pair.value
|
|
36
|
+
|
|
37
|
+
next if on_good_time_transform?(transform_node)
|
|
38
|
+
|
|
39
|
+
on_time_transform?(transform_node) do
|
|
40
|
+
add_offense(transform_node) do |corrector|
|
|
41
|
+
correction = build_autocorrection(transform_node)
|
|
42
|
+
corrector.replace(transform_node, correction) if correction
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def build_autocorrection(node)
|
|
49
|
+
<<~CODE.chomp
|
|
50
|
+
#{node.source}.using(:utc)
|
|
51
|
+
CODE
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'active_support/core_ext/enumerable'
|
|
5
|
+
require 'alchemrest'
|
|
6
|
+
|
|
7
|
+
module Tapioca
|
|
8
|
+
module Dsl
|
|
9
|
+
module Compilers
|
|
10
|
+
# This compiler generates RBI files for classes that inherit from `Alchemrest::Data`.
|
|
11
|
+
#
|
|
12
|
+
# For example, given the following class:
|
|
13
|
+
#
|
|
14
|
+
# class Profile < Alchemrest::Data
|
|
15
|
+
# schema do |s|
|
|
16
|
+
# {
|
|
17
|
+
# required: {
|
|
18
|
+
# name: s.string,
|
|
19
|
+
# },
|
|
20
|
+
# }
|
|
21
|
+
# end
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
24
|
+
# This compiler will generate an RBI file `profile.rbi` with the following content:
|
|
25
|
+
#
|
|
26
|
+
# sig { returns(::String) }
|
|
27
|
+
# def name; end
|
|
28
|
+
#
|
|
29
|
+
class AlchemrestData < Tapioca::Dsl::Compiler
|
|
30
|
+
extend T::Sig
|
|
31
|
+
|
|
32
|
+
Type = T.type_alias { T.any(Class, T::Types::Base) }
|
|
33
|
+
|
|
34
|
+
ConstantType = type_member { { upper: T.class_of(Alchemrest::Data) } }
|
|
35
|
+
|
|
36
|
+
sig { override.returns(T::Enumerable[Module]) }
|
|
37
|
+
def self.gather_constants
|
|
38
|
+
descendants_of(Alchemrest::Data)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
sig { override.void }
|
|
42
|
+
def decorate
|
|
43
|
+
root.create_path(constant) do |rbi|
|
|
44
|
+
constant.graph.fields.each do |name, field|
|
|
45
|
+
type = T::Utils.coerce(extract_type(field.output_type))
|
|
46
|
+
rbi.create_method(name.to_s, return_type: type.to_s)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
sig { params(output_type: T.nilable(Alchemrest::Transforms::OutputType)).returns(Type) }
|
|
52
|
+
def extract_type(output_type)
|
|
53
|
+
return T.untyped if output_type.nil?
|
|
54
|
+
|
|
55
|
+
output_type.sorbet_type
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
sig { params(types: T::Array[Class]).returns(Type) }
|
|
59
|
+
def extract_output_type(types)
|
|
60
|
+
types.many? ? T.any(*T.unsafe(types)) : types.sole
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
sig { params(field: Alchemrest::Data::Field).returns(T::Boolean) }
|
|
64
|
+
def nilable?(field)
|
|
65
|
+
!field.required || field.transform.is_a?(Morpher::Transform::Maybe)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
sig { params(transform: Morpher::Transform).returns(T::Boolean) }
|
|
69
|
+
def array?(transform)
|
|
70
|
+
case transform
|
|
71
|
+
when Alchemrest::Transforms::Typed
|
|
72
|
+
transform.collection
|
|
73
|
+
when Morpher::Transform::Array
|
|
74
|
+
true
|
|
75
|
+
when Morpher::Transform::Maybe
|
|
76
|
+
array?(transform.send(:transform))
|
|
77
|
+
else
|
|
78
|
+
false
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'active_support/core_ext/enumerable'
|
|
5
|
+
require 'alchemrest'
|
|
6
|
+
|
|
7
|
+
module Tapioca
|
|
8
|
+
module Dsl
|
|
9
|
+
module Compilers
|
|
10
|
+
# This compiler generates RBI files for classes that inherit from `Alchemrest::Root`.
|
|
11
|
+
#
|
|
12
|
+
# For example, given the following class:
|
|
13
|
+
#
|
|
14
|
+
# class Root < Alchemrest::Root
|
|
15
|
+
# define_request :get_profile, Requests::GetProfile
|
|
16
|
+
# end
|
|
17
|
+
#
|
|
18
|
+
# This compiler will generate an RBI file `root.rbi` with the following content:
|
|
19
|
+
#
|
|
20
|
+
# sig { params(params: T::Hash[Symbol, T.untyped]).returns(::Alchemrest::Result[::Profile]) }
|
|
21
|
+
# def get_profile(params = {}); end
|
|
22
|
+
#
|
|
23
|
+
class AlchemrestRoot < Tapioca::Dsl::Compiler
|
|
24
|
+
extend T::Sig
|
|
25
|
+
|
|
26
|
+
ConstantType = type_member { { upper: T.class_of(Alchemrest::Root) } }
|
|
27
|
+
|
|
28
|
+
sig { override.returns(T::Enumerable[Module]) }
|
|
29
|
+
def self.gather_constants
|
|
30
|
+
descendants_of(Alchemrest::Root)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
sig { override.void }
|
|
34
|
+
def decorate
|
|
35
|
+
root.create_path(constant) do |rbi|
|
|
36
|
+
constant.request_definitions.each do |name, definition|
|
|
37
|
+
rbi.create_method(
|
|
38
|
+
name.to_s,
|
|
39
|
+
parameters: [create_opt_param('params', type: 'T::Hash[Symbol, T.untyped]', default: '{}')],
|
|
40
|
+
return_type: return_type_for(definition),
|
|
41
|
+
)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
sig { params(definition: Alchemrest::RequestDefinition).returns(String) }
|
|
49
|
+
def return_type_for(definition)
|
|
50
|
+
transform = extract_transform(definition)
|
|
51
|
+
|
|
52
|
+
if transform.nil? || !transform.respond_to?(:output_type)
|
|
53
|
+
'::Alchemrest::Result[T.untyped]'
|
|
54
|
+
else
|
|
55
|
+
"::Alchemrest::Result[#{transform.output_type.sorbet_type}]"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
sig { params(definition: Alchemrest::RequestDefinition).returns(T.nilable(Alchemrest::Transforms::Typed)) }
|
|
60
|
+
def extract_transform(definition)
|
|
61
|
+
request_class = definition.instance_variable_get(:@request_class)
|
|
62
|
+
returns_modules = request_class.ancestors.grep(Alchemrest::Request::Returns)
|
|
63
|
+
returns_modules.sole.domain_type.const_get(:TRANSFORM) if returns_modules.one?
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|