alchemrest 3.2.3 → 3.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 18d7990fc6f122f5563b87c143e2290e775266f3a91924565a8d29e4e493d97f
4
- data.tar.gz: fbeed8b1ebc422f6f493adcdd81b9ddf16f8d717fb5016c7118590a9ceac4d4a
3
+ metadata.gz: e9985b9a29061ef219e09bcaf3613f0869442c425ebdef8a9c97cc4f31a40fa6
4
+ data.tar.gz: e1aacc36591d0dfe16fe59d7099a5b06fb4a1e076f8f61c8b8e7cbda0d72c7c7
5
5
  SHA512:
6
- metadata.gz: c273a26594c284ed543f58b5407d2f831026ca6398f381b9721dae5d6fd24aae212da750a59f1f75c92d5992dd8148e5ef9c7541743d56365b611ccd5cf309fc
7
- data.tar.gz: 34a0f36667395cda30c861a39b9e276390e63da3bc60372e3da354837095a9918cd36fdeae450944c45aecb7a9ff56c2a6b7493b66a22ed62bfb96efc079fa93
6
+ metadata.gz: c6f28199a64154cd0b91c830090e0b3aede1b8a073ecbd91f855975fca7535c4bad52b516649b4c9df8ccd5d3da96631aad1a26f6a09389728517dcebe79ac3a
7
+ data.tar.gz: 8aa2a756be73f88871b955cb11b8c7c56e750ebed26f570cca95a67b0df58dfff1fd41e04e8d2053bfa9dc70391f46eab36b2f0b6b75074b02662b9505f39bd7
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- alchemrest (3.2.3)
4
+ alchemrest (3.3.0)
5
5
  activerecord (>= 7.2, < 8.1)
6
6
  activesupport (>= 7.2, < 8.1)
7
7
  circuitbox (~> 2.0.0)
@@ -93,7 +93,7 @@ GEM
93
93
  crack (1.0.0)
94
94
  bigdecimal
95
95
  rexml
96
- crass (1.0.6)
96
+ crass (1.0.7)
97
97
  date (3.4.1)
98
98
  diff-lcs (1.6.2)
99
99
  drb (2.2.3)
@@ -120,7 +120,7 @@ GEM
120
120
  json (2.9.1)
121
121
  language_server-protocol (3.17.0.3)
122
122
  logger (1.7.0)
123
- loofah (2.24.0)
123
+ loofah (2.25.2)
124
124
  crass (~> 1.0.2)
125
125
  nokogiri (>= 1.12.0)
126
126
  memoizable (0.4.2)
@@ -203,8 +203,8 @@ GEM
203
203
  activesupport (>= 5.0.0)
204
204
  minitest
205
205
  nokogiri (>= 1.6)
206
- rails-html-sanitizer (1.6.2)
207
- loofah (~> 2.21)
206
+ rails-html-sanitizer (1.7.1)
207
+ loofah (~> 2.25, >= 2.25.2)
208
208
  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)
209
209
  railties (8.0.4.1)
210
210
  actionpack (= 8.0.4.1)
@@ -325,7 +325,7 @@ GEM
325
325
  addressable (>= 2.8.0)
326
326
  crack (>= 0.3.2)
327
327
  hashdiff (>= 0.4.0, < 2.0.0)
328
- yard (0.9.42)
328
+ yard (0.9.44)
329
329
  yard-sorbet (0.9.0)
330
330
  sorbet-runtime
331
331
  yard
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- alchemrest (3.2.3)
4
+ alchemrest (3.3.0)
5
5
  activerecord (>= 7.2, < 8.1)
6
6
  activesupport (>= 7.2, < 8.1)
7
7
  circuitbox (~> 2.0.0)
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- alchemrest (3.2.3)
4
+ alchemrest (3.3.0)
5
5
  activerecord (>= 7.2, < 8.1)
6
6
  activesupport (>= 7.2, < 8.1)
7
7
  circuitbox (~> 2.0.0)
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- alchemrest (3.2.3)
4
+ alchemrest (3.3.0)
5
5
  activerecord (>= 7.2, < 8.1)
6
6
  activesupport (>= 7.2, < 8.1)
7
7
  circuitbox (~> 2.0.0)
@@ -5,7 +5,7 @@ module Alchemrest
5
5
  # we want to create, and block that can extract default parameters from an Alchemrest::Root. When we want to build an
6
6
  # instance of the request, call `build_request` and pass in the root as context, with any additional parameters.
7
7
  class RequestDefinition
8
- attr_reader :name
8
+ attr_reader :name, :request_class, :builder_block
9
9
 
10
10
  def initialize(name, request_class, &block)
11
11
  @name = name
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Alchemrest
4
- VERSION = "3.2.3"
4
+ VERSION = "3.3.0"
5
5
  end
@@ -3,28 +3,44 @@
3
3
 
4
4
  require 'active_support/core_ext/enumerable'
5
5
  require 'alchemrest'
6
+ require 'prism'
6
7
 
7
8
  module Tapioca
8
9
  module Dsl
9
10
  module Compilers
10
11
  # This compiler generates RBI files for classes that inherit from `Alchemrest::Root`.
11
12
  #
12
- # For example, given the following class:
13
+ # For example, given the following classes:
14
+ #
15
+ # class UpdateProfile < Alchemrest::Request
16
+ # extend T::Sig
17
+ #
18
+ # sig { params(id: Integer, name: String).void }
19
+ # def initialize(id:, name:)
20
+ # ...
21
+ # end
22
+ #
23
+ # returns Profile
24
+ # end
13
25
  #
14
26
  # class Root < Alchemrest::Root
15
- # define_request :get_profile, Requests::GetProfile
27
+ # define_request :update_profile, UpdateProfile do |request|
28
+ # request.defaults = { id: }
29
+ # end
16
30
  # end
17
31
  #
18
32
  # This compiler will generate an RBI file `root.rbi` with the following content:
19
33
  #
20
- # sig { params(params: T::Hash[Symbol, T.untyped]).returns(::Alchemrest::Result[::Profile]) }
21
- # def get_profile(params = {}); end
34
+ # sig { params(name: ::String, id: ::Integer).returns(::Alchemrest::Result[::Profile]) }
35
+ # def update_profile(name:, id: T.unsafe(nil)); end
22
36
  #
23
37
  class AlchemrestRoot < Tapioca::Dsl::Compiler
24
38
  extend T::Sig
25
39
 
26
40
  ConstantType = type_member { { upper: T.class_of(Alchemrest::Root) } }
27
41
 
42
+ KEYWORD_PARAM_TYPES = [RBI::KwParam, RBI::KwOptParam, RBI::KwRestParam].freeze
43
+
28
44
  sig { override.returns(T::Enumerable[Module]) }
29
45
  def self.gather_constants
30
46
  descendants_of(Alchemrest::Root)
@@ -36,7 +52,7 @@ module Tapioca
36
52
  constant.request_definitions.each do |name, definition|
37
53
  rbi.create_method(
38
54
  name.to_s,
39
- parameters: [create_opt_param('params', type: 'T::Hash[Symbol, T.untyped]', default: '{}')],
55
+ parameters: parameters_for(definition),
40
56
  return_type: return_type_for(definition),
41
57
  )
42
58
  end
@@ -45,6 +61,63 @@ module Tapioca
45
61
 
46
62
  private
47
63
 
64
+ sig { params(definition: Alchemrest::RequestDefinition).returns(T::Array[RBI::TypedParam]) }
65
+ def parameters_for(definition)
66
+ parameters = compile_method_parameters_to_rbi(definition.request_class.instance_method(:initialize))
67
+
68
+ if parameters.all? { |typed_param| KEYWORD_PARAM_TYPES.include?(typed_param.param.class) }
69
+ optional_keys = defaulted_keys_for(definition) || parameters.map { |typed_param| typed_param.param.name }
70
+ with_optional_keys(parameters, optional_keys)
71
+ else
72
+ [create_opt_param('params', type: 'T::Hash[Symbol, T.untyped]', default: '{}')]
73
+ end
74
+ end
75
+
76
+ sig { params(parameters: T::Array[RBI::TypedParam], optional_keys: T::Array[String]).returns(T::Array[RBI::TypedParam]) }
77
+ def with_optional_keys(parameters, optional_keys)
78
+ parameters = parameters.map do |typed_param|
79
+ param = typed_param.param
80
+
81
+ if param.is_a?(RBI::KwParam) && optional_keys.include?(param.name)
82
+ create_kw_opt_param(param.name, type: typed_param.type, default: 'T.unsafe(nil)')
83
+ else
84
+ typed_param
85
+ end
86
+ end
87
+
88
+ required, optional = parameters.partition { |typed_param| typed_param.param.is_a?(RBI::KwParam) }
89
+ required + optional
90
+ end
91
+
92
+ sig { params(definition: Alchemrest::RequestDefinition).returns(T.nilable(T::Array[String])) }
93
+ def defaulted_keys_for(definition)
94
+ if definition.builder_block
95
+ literal_defaults_keys(block_node_for(definition.builder_block))
96
+ else
97
+ []
98
+ end
99
+ end
100
+
101
+ sig { params(block_node: T.nilable(Prism::Node)).returns(T.nilable(T::Array[String])) }
102
+ def literal_defaults_keys(block_node)
103
+ case block_node
104
+ in { body: { body: [Prism::CallNode[name: :defaults=, arguments: { arguments: [Prism::HashNode[elements:]] }]] } }
105
+ symbol_keys = elements.grep(Prism::AssocNode).map(&:key).grep(Prism::SymbolNode)
106
+ symbol_keys.map(&:unescaped) if symbol_keys.size == elements.size
107
+ else
108
+ nil
109
+ end
110
+ end
111
+
112
+ sig { params(builder_block: Proc).returns(T.nilable(Prism::Node)) }
113
+ def block_node_for(builder_block)
114
+ file, line = builder_block.source_location
115
+
116
+ if file && File.exist?(file)
117
+ Prism.parse_file(file).value.breadth_first_search { |node| node.is_a?(Prism::BlockNode) && node.location.start_line == line }
118
+ end
119
+ end
120
+
48
121
  sig { params(definition: Alchemrest::RequestDefinition).returns(String) }
49
122
  def return_type_for(definition)
50
123
  transform = extract_transform(definition)
@@ -58,8 +131,7 @@ module Tapioca
58
131
 
59
132
  sig { params(definition: Alchemrest::RequestDefinition).returns(T.nilable(Alchemrest::Transforms::Typed)) }
60
133
  def extract_transform(definition)
61
- request_class = definition.instance_variable_get(:@request_class)
62
- returns_modules = request_class.ancestors.grep(Alchemrest::Request::Returns)
134
+ returns_modules = definition.request_class.ancestors.grep(Alchemrest::Request::Returns)
63
135
  returns_modules.sole.domain_type.const_get(:TRANSFORM) if returns_modules.one?
64
136
  end
65
137
  end
@@ -8,87 +8,90 @@
8
8
  # source://crass//lib/crass/token-scanner.rb#3
9
9
  module Crass
10
10
  class << self
11
- # source://crass//lib/crass.rb#10
11
+ # source://crass//lib/crass.rb#22
12
12
  def parse(input, options = T.unsafe(nil)); end
13
13
 
14
- # source://crass//lib/crass.rb#18
14
+ # source://crass//lib/crass.rb#30
15
15
  def parse_properties(input, options = T.unsafe(nil)); end
16
16
  end
17
17
  end
18
18
 
19
19
  # source://crass//lib/crass/parser.rb#10
20
20
  class Crass::Parser
21
- # source://crass//lib/crass/parser.rb#126
21
+ # source://crass//lib/crass/parser.rb#140
22
22
  def initialize(input, options = T.unsafe(nil)); end
23
23
 
24
- # source://crass//lib/crass/parser.rb#137
24
+ # source://crass//lib/crass/parser.rb#153
25
25
  def consume_at_rule(input = T.unsafe(nil)); end
26
26
 
27
- # source://crass//lib/crass/parser.rb#184
27
+ # source://crass//lib/crass/parser.rb#200
28
28
  def consume_component_value(input = T.unsafe(nil)); end
29
29
 
30
- # source://crass//lib/crass/parser.rb#209
30
+ # source://crass//lib/crass/parser.rb#225
31
31
  def consume_declaration(input = T.unsafe(nil)); end
32
32
 
33
- # source://crass//lib/crass/parser.rb#276
33
+ # source://crass//lib/crass/parser.rb#292
34
34
  def consume_declarations(input = T.unsafe(nil), options = T.unsafe(nil)); end
35
35
 
36
- # source://crass//lib/crass/parser.rb#326
36
+ # source://crass//lib/crass/parser.rb#342
37
37
  def consume_function(input = T.unsafe(nil)); end
38
38
 
39
- # source://crass//lib/crass/parser.rb#357
39
+ # source://crass//lib/crass/parser.rb#383
40
40
  def consume_qualified_rule(input = T.unsafe(nil)); end
41
41
 
42
- # source://crass//lib/crass/parser.rb#398
42
+ # source://crass//lib/crass/parser.rb#424
43
43
  def consume_rules(flags = T.unsafe(nil)); end
44
44
 
45
- # source://crass//lib/crass/parser.rb#434
45
+ # source://crass//lib/crass/parser.rb#460
46
46
  def consume_simple_block(input = T.unsafe(nil)); end
47
47
 
48
- # source://crass//lib/crass/parser.rb#458
48
+ # source://crass//lib/crass/parser.rb#526
49
49
  def create_node(type, properties = T.unsafe(nil)); end
50
50
 
51
- # source://crass//lib/crass/parser.rb#466
51
+ # source://crass//lib/crass/parser.rb#534
52
52
  def create_selector(input); end
53
53
 
54
- # source://crass//lib/crass/parser.rb#474
54
+ # source://crass//lib/crass/parser.rb#542
55
55
  def create_style_rule(rule); end
56
56
 
57
- # source://crass//lib/crass/parser.rb#483
57
+ # source://crass//lib/crass/parser.rb#501
58
+ def discard_block(input); end
59
+
60
+ # source://crass//lib/crass/parser.rb#551
58
61
  def parse_component_value(input = T.unsafe(nil)); end
59
62
 
60
- # source://crass//lib/crass/parser.rb#510
63
+ # source://crass//lib/crass/parser.rb#578
61
64
  def parse_component_values(input = T.unsafe(nil)); end
62
65
 
63
- # source://crass//lib/crass/parser.rb#524
66
+ # source://crass//lib/crass/parser.rb#592
64
67
  def parse_declaration(input = T.unsafe(nil)); end
65
68
 
66
- # source://crass//lib/crass/parser.rb#552
69
+ # source://crass//lib/crass/parser.rb#620
67
70
  def parse_declarations(input = T.unsafe(nil), options = T.unsafe(nil)); end
68
71
 
69
- # source://crass//lib/crass/parser.rb#560
72
+ # source://crass//lib/crass/parser.rb#628
70
73
  def parse_properties(input = T.unsafe(nil)); end
71
74
 
72
- # source://crass//lib/crass/parser.rb#586
75
+ # source://crass//lib/crass/parser.rb#654
73
76
  def parse_rule(input = T.unsafe(nil)); end
74
77
 
75
- # source://crass//lib/crass/parser.rb#615
78
+ # source://crass//lib/crass/parser.rb#683
76
79
  def parse_value(nodes); end
77
80
 
78
- # source://crass//lib/crass/parser.rb#120
81
+ # source://crass//lib/crass/parser.rb#134
79
82
  def tokens; end
80
83
 
81
84
  class << self
82
- # source://crass//lib/crass/parser.rb#25
85
+ # source://crass//lib/crass/parser.rb#39
83
86
  def parse_properties(input, options = T.unsafe(nil)); end
84
87
 
85
- # source://crass//lib/crass/parser.rb#36
88
+ # source://crass//lib/crass/parser.rb#50
86
89
  def parse_rules(input, options = T.unsafe(nil)); end
87
90
 
88
- # source://crass//lib/crass/parser.rb#54
91
+ # source://crass//lib/crass/parser.rb#68
89
92
  def parse_stylesheet(input, options = T.unsafe(nil)); end
90
93
 
91
- # source://crass//lib/crass/parser.rb#74
94
+ # source://crass//lib/crass/parser.rb#88
92
95
  def stringify(nodes, options = T.unsafe(nil)); end
93
96
  end
94
97
  end
@@ -96,27 +99,30 @@ end
96
99
  # source://crass//lib/crass/parser.rb#11
97
100
  Crass::Parser::BLOCK_END_TOKENS = T.let(T.unsafe(nil), Hash)
98
101
 
102
+ # source://crass//lib/crass/parser.rb#29
103
+ Crass::Parser::DEFAULT_MAXIMUM_DEPTH = T.let(T.unsafe(nil), Integer)
104
+
99
105
  # source://crass//lib/crass/scanner.rb#8
100
106
  class Crass::Scanner
101
- # source://crass//lib/crass/scanner.rb#25
107
+ # source://crass//lib/crass/scanner.rb#29
102
108
  def initialize(input); end
103
109
 
104
- # source://crass//lib/crass/scanner.rb#34
110
+ # source://crass//lib/crass/scanner.rb#38
105
111
  def consume; end
106
112
 
107
- # source://crass//lib/crass/scanner.rb#46
113
+ # source://crass//lib/crass/scanner.rb#50
108
114
  def consume_rest; end
109
115
 
110
116
  # source://crass//lib/crass/scanner.rb#11
111
117
  def current; end
112
118
 
113
- # source://crass//lib/crass/scanner.rb#57
119
+ # source://crass//lib/crass/scanner.rb#66
114
120
  def eos?; end
115
121
 
116
- # source://crass//lib/crass/scanner.rb#63
122
+ # source://crass//lib/crass/scanner.rb#72
117
123
  def mark; end
118
124
 
119
- # source://crass//lib/crass/scanner.rb#69
125
+ # source://crass//lib/crass/scanner.rb#79
120
126
  def marked; end
121
127
 
122
128
  # source://crass//lib/crass/scanner.rb#15
@@ -125,28 +131,28 @@ class Crass::Scanner
125
131
  # source://crass//lib/crass/scanner.rb#15
126
132
  def marker=(_arg0); end
127
133
 
128
- # source://crass//lib/crass/scanner.rb#80
134
+ # source://crass//lib/crass/scanner.rb#91
129
135
  def peek(length = T.unsafe(nil)); end
130
136
 
131
- # source://crass//lib/crass/scanner.rb#19
137
+ # source://crass//lib/crass/scanner.rb#23
132
138
  def pos; end
133
139
 
134
- # source://crass//lib/crass/scanner.rb#19
140
+ # source://crass//lib/crass/scanner.rb#23
135
141
  def pos=(_arg0); end
136
142
 
137
- # source://crass//lib/crass/scanner.rb#87
143
+ # source://crass//lib/crass/scanner.rb#103
138
144
  def reconsume; end
139
145
 
140
- # source://crass//lib/crass/scanner.rb#93
146
+ # source://crass//lib/crass/scanner.rb#109
141
147
  def reset; end
142
148
 
143
- # source://crass//lib/crass/scanner.rb#103
149
+ # source://crass//lib/crass/scanner.rb#122
144
150
  def scan(pattern); end
145
151
 
146
- # source://crass//lib/crass/scanner.rb#115
152
+ # source://crass//lib/crass/scanner.rb#134
147
153
  def scan_until(pattern); end
148
154
 
149
- # source://crass//lib/crass/scanner.rb#22
155
+ # source://crass//lib/crass/scanner.rb#26
150
156
  def string; end
151
157
  end
152
158
 
@@ -188,55 +194,55 @@ class Crass::Tokenizer
188
194
  # source://crass//lib/crass/tokenizer.rb#70
189
195
  def consume; end
190
196
 
191
- # source://crass//lib/crass/tokenizer.rb#275
197
+ # source://crass//lib/crass/tokenizer.rb#276
192
198
  def consume_bad_url; end
193
199
 
194
- # source://crass//lib/crass/tokenizer.rb#301
200
+ # source://crass//lib/crass/tokenizer.rb#302
195
201
  def consume_comments; end
196
202
 
197
- # source://crass//lib/crass/tokenizer.rb#326
203
+ # source://crass//lib/crass/tokenizer.rb#327
198
204
  def consume_escaped; end
199
205
 
200
- # source://crass//lib/crass/tokenizer.rb#350
206
+ # source://crass//lib/crass/tokenizer.rb#351
201
207
  def consume_ident; end
202
208
 
203
- # source://crass//lib/crass/tokenizer.rb#375
209
+ # source://crass//lib/crass/tokenizer.rb#376
204
210
  def consume_name; end
205
211
 
206
- # source://crass//lib/crass/tokenizer.rb#407
212
+ # source://crass//lib/crass/tokenizer.rb#408
207
213
  def consume_number; end
208
214
 
209
- # source://crass//lib/crass/tokenizer.rb#430
215
+ # source://crass//lib/crass/tokenizer.rb#431
210
216
  def consume_numeric; end
211
217
 
212
- # source://crass//lib/crass/tokenizer.rb#469
218
+ # source://crass//lib/crass/tokenizer.rb#470
213
219
  def consume_string(ending = T.unsafe(nil)); end
214
220
 
215
- # source://crass//lib/crass/tokenizer.rb#510
221
+ # source://crass//lib/crass/tokenizer.rb#511
216
222
  def consume_unicode_range; end
217
223
 
218
- # source://crass//lib/crass/tokenizer.rb#542
224
+ # source://crass//lib/crass/tokenizer.rb#543
219
225
  def consume_url; end
220
226
 
221
- # source://crass//lib/crass/tokenizer.rb#590
227
+ # source://crass//lib/crass/tokenizer.rb#591
222
228
  def convert_string_to_number(str); end
223
229
 
224
- # source://crass//lib/crass/tokenizer.rb#616
230
+ # source://crass//lib/crass/tokenizer.rb#643
225
231
  def create_token(type, properties = T.unsafe(nil)); end
226
232
 
227
- # source://crass//lib/crass/tokenizer.rb#627
233
+ # source://crass//lib/crass/tokenizer.rb#654
228
234
  def preprocess(input); end
229
235
 
230
- # source://crass//lib/crass/tokenizer.rb#642
236
+ # source://crass//lib/crass/tokenizer.rb#669
231
237
  def start_identifier?(text = T.unsafe(nil)); end
232
238
 
233
- # source://crass//lib/crass/tokenizer.rb#666
239
+ # source://crass//lib/crass/tokenizer.rb#693
234
240
  def start_number?(text = T.unsafe(nil)); end
235
241
 
236
- # source://crass//lib/crass/tokenizer.rb#685
242
+ # source://crass//lib/crass/tokenizer.rb#712
237
243
  def tokenize; end
238
244
 
239
- # source://crass//lib/crass/tokenizer.rb#702
245
+ # source://crass//lib/crass/tokenizer.rb#729
240
246
  def valid_escape?(text = T.unsafe(nil)); end
241
247
 
242
248
  class << self