lithic 0.1.0.pre.alpha.32 → 0.1.0.pre.alpha.34
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 +4 -4
- data/CHANGELOG.md +21 -0
- data/README.md +1 -1
- data/lib/lithic/client.rb +4 -0
- data/lib/lithic/errors.rb +22 -0
- data/lib/lithic/internal/type/array_of.rb +6 -1
- data/lib/lithic/internal/type/base_model.rb +77 -25
- data/lib/lithic/internal/type/boolean.rb +7 -1
- data/lib/lithic/internal/type/converter.rb +42 -34
- data/lib/lithic/internal/type/enum.rb +10 -2
- data/lib/lithic/internal/type/file_input.rb +6 -1
- data/lib/lithic/internal/type/hash_of.rb +6 -1
- data/lib/lithic/internal/type/union.rb +12 -7
- data/lib/lithic/internal/type/unknown.rb +7 -1
- data/lib/lithic/models/auth_rules/rule_stats.rb +112 -0
- data/lib/lithic/models/auth_rules/v2/backtest_results.rb +6 -238
- data/lib/lithic/models/auth_rules/v2_retrieve_report_params.rb +32 -0
- data/lib/lithic/models/auth_rules/v2_retrieve_report_response.rb +71 -0
- data/lib/lithic/models/card_convert_physical_params.rb +10 -6
- data/lib/lithic/models/card_create_params.rb +10 -6
- data/lib/lithic/models/card_reissue_params.rb +10 -6
- data/lib/lithic/models/card_renew_params.rb +10 -6
- data/lib/lithic/models/external_bank_account_create_params.rb +1 -1
- data/lib/lithic/models/financial_accounts/statements/statement_line_items.rb +1 -0
- data/lib/lithic/models/financial_transaction.rb +1 -0
- data/lib/lithic/models/fraud/transaction_report_params.rb +130 -0
- data/lib/lithic/models/fraud/transaction_report_response.rb +160 -0
- data/lib/lithic/models/fraud/transaction_retrieve_params.rb +16 -0
- data/lib/lithic/models/fraud/transaction_retrieve_response.rb +160 -0
- data/lib/lithic/models/payment.rb +7 -1
- data/lib/lithic/models/payment_create_params.rb +7 -1
- data/lib/lithic/models/three_ds/authentication_retrieve_response.rb +111 -79
- data/lib/lithic/models/three_ds/authentication_simulate_params.rb +8 -2
- data/lib/lithic/models/three_ds/authentication_simulate_response.rb +2 -6
- data/lib/lithic/models/three_ds/challenge_response.rb +7 -7
- data/lib/lithic/models/three_ds/challenge_result.rb +1 -1
- data/lib/lithic/models/transfer.rb +1 -0
- data/lib/lithic/models.rb +2 -0
- data/lib/lithic/resources/auth_rules/v2/backtests.rb +8 -7
- data/lib/lithic/resources/auth_rules/v2.rb +45 -4
- data/lib/lithic/resources/fraud/transactions.rb +69 -0
- data/lib/lithic/resources/fraud.rb +18 -0
- data/lib/lithic/resources/three_ds/authentication.rb +6 -6
- data/lib/lithic/resources/three_ds/decisioning.rb +8 -3
- data/lib/lithic/version.rb +1 -1
- data/lib/lithic.rb +9 -0
- data/rbi/lithic/client.rbi +3 -0
- data/rbi/lithic/errors.rbi +16 -0
- data/rbi/lithic/internal/type/boolean.rbi +2 -0
- data/rbi/lithic/internal/type/converter.rbi +15 -15
- data/rbi/lithic/internal/type/union.rbi +5 -0
- data/rbi/lithic/internal/type/unknown.rbi +2 -0
- data/rbi/lithic/models/auth_rules/rule_stats.rbi +229 -0
- data/rbi/lithic/models/auth_rules/v2/backtest_results.rbi +8 -523
- data/rbi/lithic/models/auth_rules/v2_retrieve_report_params.rbi +56 -0
- data/rbi/lithic/models/auth_rules/v2_retrieve_report_response.rbi +149 -0
- data/rbi/lithic/models/card_convert_physical_params.rbi +15 -9
- data/rbi/lithic/models/card_create_params.rbi +15 -9
- data/rbi/lithic/models/card_reissue_params.rbi +15 -9
- data/rbi/lithic/models/card_renew_params.rbi +15 -9
- data/rbi/lithic/models/external_bank_account_create_params.rbi +2 -2
- data/rbi/lithic/models/financial_accounts/statements/statement_line_items.rbi +5 -0
- data/rbi/lithic/models/financial_transaction.rbi +5 -0
- data/rbi/lithic/models/fraud/transaction_report_params.rbi +263 -0
- data/rbi/lithic/models/fraud/transaction_report_response.rbi +309 -0
- data/rbi/lithic/models/fraud/transaction_retrieve_params.rbi +32 -0
- data/rbi/lithic/models/fraud/transaction_retrieve_response.rbi +309 -0
- data/rbi/lithic/models/payment.rbi +9 -3
- data/rbi/lithic/models/payment_create_params.rbi +8 -3
- data/rbi/lithic/models/three_ds/authentication_retrieve_response.rbi +171 -108
- data/rbi/lithic/models/three_ds/authentication_simulate_params.rbi +6 -0
- data/rbi/lithic/models/three_ds/authentication_simulate_response.rbi +2 -4
- data/rbi/lithic/models/three_ds/challenge_response.rbi +7 -10
- data/rbi/lithic/models/three_ds/challenge_result.rbi +1 -1
- data/rbi/lithic/models/transfer.rbi +2 -0
- data/rbi/lithic/models.rbi +2 -0
- data/rbi/lithic/resources/auth_rules/v2/backtests.rbi +8 -7
- data/rbi/lithic/resources/auth_rules/v2.rbi +37 -4
- data/rbi/lithic/resources/cards.rbi +20 -12
- data/rbi/lithic/resources/fraud/transactions.rbi +86 -0
- data/rbi/lithic/resources/fraud.rbi +15 -0
- data/rbi/lithic/resources/three_ds/authentication.rbi +6 -4
- data/rbi/lithic/resources/three_ds/decisioning.rbi +9 -6
- data/sig/lithic/client.rbs +2 -0
- data/sig/lithic/errors.rbs +9 -0
- data/sig/lithic/internal/type/converter.rbs +7 -1
- data/sig/lithic/models/auth_rules/rule_stats.rbs +108 -0
- data/sig/lithic/models/auth_rules/v2/backtest_results.rbs +8 -214
- data/sig/lithic/models/auth_rules/v2_retrieve_report_params.rbs +30 -0
- data/sig/lithic/models/auth_rules/v2_retrieve_report_response.rbs +64 -0
- data/sig/lithic/models/external_bank_account_create_params.rbs +2 -2
- data/sig/lithic/models/financial_accounts/statements/statement_line_items.rbs +2 -0
- data/sig/lithic/models/financial_transaction.rbs +2 -0
- data/sig/lithic/models/fraud/transaction_report_params.rbs +75 -0
- data/sig/lithic/models/fraud/transaction_report_response.rbs +90 -0
- data/sig/lithic/models/fraud/transaction_retrieve_params.rbs +17 -0
- data/sig/lithic/models/fraud/transaction_retrieve_response.rbs +90 -0
- data/sig/lithic/models/payment.rbs +8 -3
- data/sig/lithic/models/payment_create_params.rbs +8 -3
- data/sig/lithic/models/three_ds/authentication_retrieve_response.rbs +19 -20
- data/sig/lithic/models/transfer.rbs +2 -0
- data/sig/lithic/models.rbs +2 -0
- data/sig/lithic/resources/auth_rules/v2.rbs +7 -0
- data/sig/lithic/resources/fraud/transactions.rbs +22 -0
- data/sig/lithic/resources/fraud.rbs +9 -0
- metadata +29 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fc2b97724913cf259b2ddeaea843b6f8d6e13750145554108b6d1d695ef18543
|
4
|
+
data.tar.gz: f9160e474aa8fb0aceaf9a5fdb3b2478caed27cda5c96489bef2c2b9c449f1e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b873bd933dbddcbce2206ea4d35604ce9714fb120675c4296bc6f2a0bc992951d54ed59f08e478a459553f92aced06a85aca339d4ff5295d404a0965ff7b048
|
7
|
+
data.tar.gz: 7428fb3a12056ee6ed8cad57d00f7a1abf00285ee07f9c8f0d7e94ddab003eaf3ac9fd8ce831868b69afb0594bdcbcecd6f91983a35b328eddf9ae6cfbde83f3
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.1.0-alpha.34 (2025-06-26)
|
4
|
+
|
5
|
+
Full Changelog: [v0.1.0-alpha.33...v0.1.0-alpha.34](https://github.com/lithic-com/lithic-ruby/compare/v0.1.0-alpha.33...v0.1.0-alpha.34)
|
6
|
+
|
7
|
+
### Features
|
8
|
+
|
9
|
+
* **client:** adds support for on-demand Auth Rule Performance Reports ([54fcb64](https://github.com/lithic-com/lithic-ruby/commit/54fcb64ea4678afd8049d070b5f28873beeec3a4))
|
10
|
+
|
11
|
+
|
12
|
+
### Bug Fixes
|
13
|
+
|
14
|
+
* **ci:** release-doctor — report correct token name ([664a344](https://github.com/lithic-com/lithic-ruby/commit/664a344c803fc568d8011c18acb0246564a589ec))
|
15
|
+
|
16
|
+
## 0.1.0-alpha.33 (2025-06-18)
|
17
|
+
|
18
|
+
Full Changelog: [v0.1.0-alpha.32...v0.1.0-alpha.33](https://github.com/lithic-com/lithic-ruby/compare/v0.1.0-alpha.32...v0.1.0-alpha.33)
|
19
|
+
|
20
|
+
### Bug Fixes
|
21
|
+
|
22
|
+
* issue where we cannot mutate arrays on base model derivatives ([d9e95e7](https://github.com/lithic-com/lithic-ruby/commit/d9e95e745161befcf4908ea5fad28b5a9a30c131))
|
23
|
+
|
3
24
|
## 0.1.0-alpha.32 (2025-06-17)
|
4
25
|
|
5
26
|
Full Changelog: [v0.1.0-alpha.31...v0.1.0-alpha.32](https://github.com/lithic-com/lithic-ruby/compare/v0.1.0-alpha.31...v0.1.0-alpha.32)
|
data/README.md
CHANGED
@@ -15,7 +15,7 @@ To use this gem, install via Bundler by adding the following to your application
|
|
15
15
|
<!-- x-release-please-start-version -->
|
16
16
|
|
17
17
|
```ruby
|
18
|
-
gem "lithic", "~> 0.1.0.pre.alpha.
|
18
|
+
gem "lithic", "~> 0.1.0.pre.alpha.34"
|
19
19
|
```
|
20
20
|
|
21
21
|
<!-- x-release-please-end -->
|
data/lib/lithic/client.rb
CHANGED
@@ -101,6 +101,9 @@ module Lithic
|
|
101
101
|
# @return [Lithic::Resources::FundingEvents]
|
102
102
|
attr_reader :funding_events
|
103
103
|
|
104
|
+
# @return [Lithic::Resources::Fraud]
|
105
|
+
attr_reader :fraud
|
106
|
+
|
104
107
|
# Status of api
|
105
108
|
#
|
106
109
|
# @overload api_status(request_options: {})
|
@@ -201,6 +204,7 @@ module Lithic
|
|
201
204
|
@external_payments = Lithic::Resources::ExternalPayments.new(client: self)
|
202
205
|
@management_operations = Lithic::Resources::ManagementOperations.new(client: self)
|
203
206
|
@funding_events = Lithic::Resources::FundingEvents.new(client: self)
|
207
|
+
@fraud = Lithic::Resources::Fraud.new(client: self)
|
204
208
|
end
|
205
209
|
end
|
206
210
|
end
|
data/lib/lithic/errors.rb
CHANGED
@@ -9,6 +9,28 @@ module Lithic
|
|
9
9
|
end
|
10
10
|
|
11
11
|
class ConversionError < Lithic::Errors::Error
|
12
|
+
# @return [StandardError, nil]
|
13
|
+
def cause = @cause.nil? ? super : @cause
|
14
|
+
|
15
|
+
# @api private
|
16
|
+
#
|
17
|
+
# @param on [Class<StandardError>]
|
18
|
+
# @param method [Symbol]
|
19
|
+
# @param target [Object]
|
20
|
+
# @param value [Object]
|
21
|
+
# @param cause [StandardError, nil]
|
22
|
+
def initialize(on:, method:, target:, value:, cause: nil)
|
23
|
+
cls = on.name.split("::").last
|
24
|
+
|
25
|
+
message = [
|
26
|
+
"Failed to parse #{cls}.#{method} from #{value.class} to #{target.inspect}.",
|
27
|
+
"To get the unparsed API response, use #{cls}[#{method.inspect}].",
|
28
|
+
cause && "Cause: #{cause.message}"
|
29
|
+
].filter(&:itself).join(" ")
|
30
|
+
|
31
|
+
@cause = cause
|
32
|
+
super(message)
|
33
|
+
end
|
12
34
|
end
|
13
35
|
|
14
36
|
class APIError < Lithic::Errors::Error
|
@@ -62,10 +62,14 @@ module Lithic
|
|
62
62
|
#
|
63
63
|
# @param state [Hash{Symbol=>Object}] .
|
64
64
|
#
|
65
|
-
# @option state [Boolean
|
65
|
+
# @option state [Boolean] :translate_names
|
66
|
+
#
|
67
|
+
# @option state [Boolean] :strictness
|
66
68
|
#
|
67
69
|
# @option state [Hash{Symbol=>Object}] :exactness
|
68
70
|
#
|
71
|
+
# @option state [Class<StandardError>] :error
|
72
|
+
#
|
69
73
|
# @option state [Integer] :branched
|
70
74
|
#
|
71
75
|
# @return [Array<Object>, Object]
|
@@ -74,6 +78,7 @@ module Lithic
|
|
74
78
|
|
75
79
|
unless value.is_a?(Array)
|
76
80
|
exactness[:no] += 1
|
81
|
+
state[:error] = TypeError.new("#{value.class} can't be coerced into #{Array}")
|
77
82
|
return value
|
78
83
|
end
|
79
84
|
|
@@ -60,7 +60,7 @@ module Lithic
|
|
60
60
|
[Lithic::Internal::Type::Converter.type_info(type_info), type_info]
|
61
61
|
end
|
62
62
|
|
63
|
-
setter = "#{name_sym}="
|
63
|
+
setter = :"#{name_sym}="
|
64
64
|
api_name = info.fetch(:api_name, name_sym)
|
65
65
|
nilable = info.fetch(:nil?, false)
|
66
66
|
const = required && !nilable ? info.fetch(:const, Lithic::Internal::OMIT) : Lithic::Internal::OMIT
|
@@ -77,30 +77,61 @@ module Lithic
|
|
77
77
|
type_fn: type_fn
|
78
78
|
}
|
79
79
|
|
80
|
-
define_method(setter)
|
80
|
+
define_method(setter) do |value|
|
81
|
+
target = type_fn.call
|
82
|
+
state = Lithic::Internal::Type::Converter.new_coerce_state(translate_names: false)
|
83
|
+
coerced = Lithic::Internal::Type::Converter.coerce(target, value, state: state)
|
84
|
+
status = @coerced.store(name_sym, state.fetch(:error) || true)
|
85
|
+
stored =
|
86
|
+
case [target, status]
|
87
|
+
in [Lithic::Internal::Type::Converter | Symbol, true]
|
88
|
+
coerced
|
89
|
+
else
|
90
|
+
value
|
91
|
+
end
|
92
|
+
@data.store(name_sym, stored)
|
93
|
+
end
|
81
94
|
|
95
|
+
# rubocop:disable Style/CaseEquality
|
96
|
+
# rubocop:disable Metrics/BlockLength
|
82
97
|
define_method(name_sym) do
|
83
98
|
target = type_fn.call
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
Lithic::
|
90
|
-
|
91
|
-
|
92
|
-
|
99
|
+
|
100
|
+
case @coerced[name_sym]
|
101
|
+
in true | false if Lithic::Internal::Type::Converter === target
|
102
|
+
@data.fetch(name_sym)
|
103
|
+
in ::StandardError => e
|
104
|
+
raise Lithic::Errors::ConversionError.new(
|
105
|
+
on: self.class,
|
106
|
+
method: __method__,
|
107
|
+
target: target,
|
108
|
+
value: @data.fetch(name_sym),
|
109
|
+
cause: e
|
93
110
|
)
|
111
|
+
else
|
112
|
+
Kernel.then do
|
113
|
+
value = @data.fetch(name_sym) { const == Lithic::Internal::OMIT ? nil : const }
|
114
|
+
state = Lithic::Internal::Type::Converter.new_coerce_state(translate_names: false)
|
115
|
+
if (nilable || !required) && value.nil?
|
116
|
+
nil
|
117
|
+
else
|
118
|
+
Lithic::Internal::Type::Converter.coerce(
|
119
|
+
target, value, state: state
|
120
|
+
)
|
121
|
+
end
|
122
|
+
rescue StandardError => e
|
123
|
+
raise Lithic::Errors::ConversionError.new(
|
124
|
+
on: self.class,
|
125
|
+
method: __method__,
|
126
|
+
target: target,
|
127
|
+
value: value,
|
128
|
+
cause: e
|
129
|
+
)
|
130
|
+
end
|
94
131
|
end
|
95
|
-
rescue StandardError => e
|
96
|
-
cls = self.class.name.split("::").last
|
97
|
-
message = [
|
98
|
-
"Failed to parse #{cls}.#{__method__} from #{value.class} to #{target.inspect}.",
|
99
|
-
"To get the unparsed API response, use #{cls}[#{__method__.inspect}].",
|
100
|
-
"Cause: #{e.message}"
|
101
|
-
].join(" ")
|
102
|
-
raise Lithic::Errors::ConversionError.new(message)
|
103
132
|
end
|
133
|
+
# rubocop:enable Metrics/BlockLength
|
134
|
+
# rubocop:enable Style/CaseEquality
|
104
135
|
end
|
105
136
|
|
106
137
|
# @api private
|
@@ -200,23 +231,28 @@ module Lithic
|
|
200
231
|
#
|
201
232
|
# @param state [Hash{Symbol=>Object}] .
|
202
233
|
#
|
203
|
-
# @option state [Boolean
|
234
|
+
# @option state [Boolean] :translate_names
|
235
|
+
#
|
236
|
+
# @option state [Boolean] :strictness
|
204
237
|
#
|
205
238
|
# @option state [Hash{Symbol=>Object}] :exactness
|
206
239
|
#
|
240
|
+
# @option state [Class<StandardError>] :error
|
241
|
+
#
|
207
242
|
# @option state [Integer] :branched
|
208
243
|
#
|
209
244
|
# @return [self, Object]
|
210
245
|
def coerce(value, state:)
|
211
246
|
exactness = state.fetch(:exactness)
|
212
247
|
|
213
|
-
if value.is_a?(self
|
248
|
+
if value.is_a?(self)
|
214
249
|
exactness[:yes] += 1
|
215
250
|
return value
|
216
251
|
end
|
217
252
|
|
218
253
|
unless (val = Lithic::Internal::Util.coerce_hash(value)).is_a?(Hash)
|
219
254
|
exactness[:no] += 1
|
255
|
+
state[:error] = TypeError.new("#{value.class} can't be coerced into #{Hash}")
|
220
256
|
return value
|
221
257
|
end
|
222
258
|
exactness[:yes] += 1
|
@@ -224,13 +260,15 @@ module Lithic
|
|
224
260
|
keys = val.keys.to_set
|
225
261
|
instance = new
|
226
262
|
data = instance.to_h
|
263
|
+
status = instance.instance_variable_get(:@coerced)
|
227
264
|
|
228
265
|
# rubocop:disable Metrics/BlockLength
|
229
266
|
fields.each do |name, field|
|
230
267
|
mode, required, target = field.fetch_values(:mode, :required, :type)
|
231
268
|
api_name, nilable, const = field.fetch_values(:api_name, :nilable, :const)
|
269
|
+
src_name = state.fetch(:translate_names) ? api_name : name
|
232
270
|
|
233
|
-
unless val.key?(
|
271
|
+
unless val.key?(src_name)
|
234
272
|
if required && mode != :dump && const == Lithic::Internal::OMIT
|
235
273
|
exactness[nilable ? :maybe : :no] += 1
|
236
274
|
else
|
@@ -239,9 +277,10 @@ module Lithic
|
|
239
277
|
next
|
240
278
|
end
|
241
279
|
|
242
|
-
item = val.fetch(
|
243
|
-
keys.delete(
|
280
|
+
item = val.fetch(src_name)
|
281
|
+
keys.delete(src_name)
|
244
282
|
|
283
|
+
state[:error] = nil
|
245
284
|
converted =
|
246
285
|
if item.nil? && (nilable || !required)
|
247
286
|
exactness[nilable ? :yes : :maybe] += 1
|
@@ -255,6 +294,8 @@ module Lithic
|
|
255
294
|
item
|
256
295
|
end
|
257
296
|
end
|
297
|
+
|
298
|
+
status.store(name, state.fetch(:error) || true)
|
258
299
|
data.store(name, converted)
|
259
300
|
end
|
260
301
|
# rubocop:enable Metrics/BlockLength
|
@@ -430,7 +471,18 @@ module Lithic
|
|
430
471
|
# Create a new instance of a model.
|
431
472
|
#
|
432
473
|
# @param data [Hash{Symbol=>Object}, self]
|
433
|
-
def initialize(data = {})
|
474
|
+
def initialize(data = {})
|
475
|
+
@data = {}
|
476
|
+
@coerced = {}
|
477
|
+
Lithic::Internal::Util.coerce_hash!(data).each do
|
478
|
+
if self.class.known_fields.key?(_1)
|
479
|
+
public_send(:"#{_1}=", _2)
|
480
|
+
else
|
481
|
+
@data.store(_1, _2)
|
482
|
+
@coerced.store(_1, false)
|
483
|
+
end
|
484
|
+
end
|
485
|
+
end
|
434
486
|
|
435
487
|
class << self
|
436
488
|
# @api private
|
@@ -31,14 +31,20 @@ module Lithic
|
|
31
31
|
class << self
|
32
32
|
# @api private
|
33
33
|
#
|
34
|
+
# Coerce value to Boolean if possible, otherwise return the original value.
|
35
|
+
#
|
34
36
|
# @param value [Boolean, Object]
|
35
37
|
#
|
36
38
|
# @param state [Hash{Symbol=>Object}] .
|
37
39
|
#
|
38
|
-
# @option state [Boolean
|
40
|
+
# @option state [Boolean] :translate_names
|
41
|
+
#
|
42
|
+
# @option state [Boolean] :strictness
|
39
43
|
#
|
40
44
|
# @option state [Hash{Symbol=>Object}] :exactness
|
41
45
|
#
|
46
|
+
# @option state [Class<StandardError>] :error
|
47
|
+
#
|
42
48
|
# @option state [Integer] :branched
|
43
49
|
#
|
44
50
|
# @return [Boolean, Object]
|
@@ -15,10 +15,14 @@ module Lithic
|
|
15
15
|
#
|
16
16
|
# @param state [Hash{Symbol=>Object}] .
|
17
17
|
#
|
18
|
-
# @option state [Boolean
|
18
|
+
# @option state [Boolean] :translate_names
|
19
|
+
#
|
20
|
+
# @option state [Boolean] :strictness
|
19
21
|
#
|
20
22
|
# @option state [Hash{Symbol=>Object}] :exactness
|
21
23
|
#
|
24
|
+
# @option state [Class<StandardError>] :error
|
25
|
+
#
|
22
26
|
# @option state [Integer] :branched
|
23
27
|
#
|
24
28
|
# @return [Object]
|
@@ -94,6 +98,21 @@ module Lithic
|
|
94
98
|
end
|
95
99
|
end
|
96
100
|
|
101
|
+
# @api private
|
102
|
+
#
|
103
|
+
# @param translate_names [Boolean]
|
104
|
+
#
|
105
|
+
# @return [Hash{Symbol=>Object}]
|
106
|
+
def new_coerce_state(translate_names: true)
|
107
|
+
{
|
108
|
+
translate_names: translate_names,
|
109
|
+
strictness: true,
|
110
|
+
exactness: {yes: 0, no: 0, maybe: 0},
|
111
|
+
error: nil,
|
112
|
+
branched: 0
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
97
116
|
# @api private
|
98
117
|
#
|
99
118
|
# Based on `target`, transform `value` into `target`, to the extent possible:
|
@@ -110,14 +129,11 @@ module Lithic
|
|
110
129
|
#
|
111
130
|
# @param value [Object]
|
112
131
|
#
|
113
|
-
# @param state [Hash{Symbol=>Object}] The `strictness` is one of `true`, `false
|
114
|
-
#
|
115
|
-
# targets:
|
132
|
+
# @param state [Hash{Symbol=>Object}] The `strictness` is one of `true`, `false`. This informs the coercion strategy
|
133
|
+
# when we have to decide between multiple possible conversion targets:
|
116
134
|
#
|
117
135
|
# - `true`: the conversion must be exact, with minimum coercion.
|
118
136
|
# - `false`: the conversion can be approximate, with some coercion.
|
119
|
-
# - `:strong`: the conversion must be exact, with no coercion, and raise an error
|
120
|
-
# if not possible.
|
121
137
|
#
|
122
138
|
# The `exactness` is `Hash` with keys being one of `yes`, `no`, or `maybe`. For
|
123
139
|
# any given conversion attempt, the exactness will be updated based on how closely
|
@@ -130,21 +146,20 @@ module Lithic
|
|
130
146
|
#
|
131
147
|
# See implementation below for more details.
|
132
148
|
#
|
133
|
-
# @option state [Boolean
|
149
|
+
# @option state [Boolean] :translate_names
|
150
|
+
#
|
151
|
+
# @option state [Boolean] :strictness
|
134
152
|
#
|
135
153
|
# @option state [Hash{Symbol=>Object}] :exactness
|
136
154
|
#
|
155
|
+
# @option state [Class<StandardError>] :error
|
156
|
+
#
|
137
157
|
# @option state [Integer] :branched
|
138
158
|
#
|
139
159
|
# @return [Object]
|
140
|
-
def coerce(
|
141
|
-
target,
|
142
|
-
value,
|
143
|
-
state: {strictness: true, exactness: {yes: 0, no: 0, maybe: 0}, branched: 0}
|
144
|
-
)
|
145
|
-
# rubocop:disable Lint/SuppressedException
|
160
|
+
def coerce(target, value, state: Lithic::Internal::Type::Converter.new_coerce_state)
|
146
161
|
# rubocop:disable Metrics/BlockNesting
|
147
|
-
|
162
|
+
exactness = state.fetch(:exactness)
|
148
163
|
|
149
164
|
case target
|
150
165
|
in Lithic::Internal::Type::Converter
|
@@ -160,29 +175,26 @@ module Lithic
|
|
160
175
|
exactness[value.nil? ? :yes : :maybe] += 1
|
161
176
|
return nil
|
162
177
|
in -> { _1 <= Integer }
|
163
|
-
|
178
|
+
case value
|
179
|
+
in Integer
|
164
180
|
exactness[:yes] += 1
|
165
181
|
return value
|
166
|
-
elsif strictness == :strong && Integer(value, exception: false) != value
|
167
|
-
message = "no implicit conversion of #{value.class} into #{target.inspect}"
|
168
|
-
raise value.is_a?(Numeric) ? ArgumentError.new(message) : TypeError.new(message)
|
169
182
|
else
|
170
183
|
Kernel.then do
|
171
184
|
return Integer(value).tap { exactness[:maybe] += 1 }
|
172
|
-
rescue ArgumentError, TypeError
|
185
|
+
rescue ArgumentError, TypeError => e
|
186
|
+
state[:error] = e
|
173
187
|
end
|
174
188
|
end
|
175
189
|
in -> { _1 <= Float }
|
176
190
|
if value.is_a?(Numeric)
|
177
191
|
exactness[:yes] += 1
|
178
192
|
return Float(value)
|
179
|
-
elsif strictness == :strong
|
180
|
-
message = "no implicit conversion of #{value.class} into #{target.inspect}"
|
181
|
-
raise TypeError.new(message)
|
182
193
|
else
|
183
194
|
Kernel.then do
|
184
195
|
return Float(value).tap { exactness[:maybe] += 1 }
|
185
|
-
rescue ArgumentError, TypeError
|
196
|
+
rescue ArgumentError, TypeError => e
|
197
|
+
state[:error] = e
|
186
198
|
end
|
187
199
|
end
|
188
200
|
in -> { _1 <= String }
|
@@ -194,16 +206,13 @@ module Lithic
|
|
194
206
|
exactness[:yes] += 1
|
195
207
|
return value.string
|
196
208
|
else
|
197
|
-
|
198
|
-
message = "no implicit conversion of #{value.class} into #{target.inspect}"
|
199
|
-
raise TypeError.new(message)
|
200
|
-
end
|
209
|
+
state[:error] = TypeError.new("#{value.class} can't be coerced into #{String}")
|
201
210
|
end
|
202
211
|
in -> { _1 <= Date || _1 <= Time }
|
203
212
|
Kernel.then do
|
204
213
|
return target.parse(value).tap { exactness[:yes] += 1 }
|
205
214
|
rescue ArgumentError, TypeError => e
|
206
|
-
|
215
|
+
state[:error] = e
|
207
216
|
end
|
208
217
|
in -> { _1 <= StringIO } if value.is_a?(String)
|
209
218
|
exactness[:yes] += 1
|
@@ -221,10 +230,8 @@ module Lithic
|
|
221
230
|
return value
|
222
231
|
end
|
223
232
|
else
|
224
|
-
|
225
|
-
|
226
|
-
raise ArgumentError.new(message)
|
227
|
-
end
|
233
|
+
message = "cannot convert non-matching #{value.class} into #{target.inspect}"
|
234
|
+
state[:error] = ArgumentError.new(message)
|
228
235
|
end
|
229
236
|
else
|
230
237
|
end
|
@@ -232,7 +239,6 @@ module Lithic
|
|
232
239
|
exactness[:no] += 1
|
233
240
|
value
|
234
241
|
# rubocop:enable Metrics/BlockNesting
|
235
|
-
# rubocop:enable Lint/SuppressedException
|
236
242
|
end
|
237
243
|
|
238
244
|
# @api private
|
@@ -277,8 +283,10 @@ module Lithic
|
|
277
283
|
define_sorbet_constant!(:CoerceState) do
|
278
284
|
T.type_alias do
|
279
285
|
{
|
280
|
-
|
286
|
+
translate_names: T::Boolean,
|
287
|
+
strictness: T::Boolean,
|
281
288
|
exactness: {yes: Integer, no: Integer, maybe: Integer},
|
289
|
+
error: T::Class[StandardError],
|
282
290
|
branched: Integer
|
283
291
|
}
|
284
292
|
end
|
@@ -77,10 +77,14 @@ module Lithic
|
|
77
77
|
#
|
78
78
|
# @param state [Hash{Symbol=>Object}] .
|
79
79
|
#
|
80
|
-
# @option state [Boolean
|
80
|
+
# @option state [Boolean] :translate_names
|
81
|
+
#
|
82
|
+
# @option state [Boolean] :strictness
|
81
83
|
#
|
82
84
|
# @option state [Hash{Symbol=>Object}] :exactness
|
83
85
|
#
|
86
|
+
# @option state [Class<StandardError>] :error
|
87
|
+
#
|
84
88
|
# @option state [Integer] :branched
|
85
89
|
#
|
86
90
|
# @return [Symbol, Object]
|
@@ -91,8 +95,12 @@ module Lithic
|
|
91
95
|
if values.include?(val)
|
92
96
|
exactness[:yes] += 1
|
93
97
|
val
|
98
|
+
elsif values.first&.class == val.class
|
99
|
+
exactness[:maybe] += 1
|
100
|
+
value
|
94
101
|
else
|
95
|
-
exactness[
|
102
|
+
exactness[:no] += 1
|
103
|
+
state[:error] = TypeError.new("#{value.class} can't be coerced into #{self}")
|
96
104
|
value
|
97
105
|
end
|
98
106
|
end
|
@@ -45,10 +45,14 @@ module Lithic
|
|
45
45
|
#
|
46
46
|
# @param state [Hash{Symbol=>Object}] .
|
47
47
|
#
|
48
|
-
# @option state [Boolean
|
48
|
+
# @option state [Boolean] :translate_names
|
49
|
+
#
|
50
|
+
# @option state [Boolean] :strictness
|
49
51
|
#
|
50
52
|
# @option state [Hash{Symbol=>Object}] :exactness
|
51
53
|
#
|
54
|
+
# @option state [Class<StandardError>] :error
|
55
|
+
#
|
52
56
|
# @option state [Integer] :branched
|
53
57
|
#
|
54
58
|
# @return [StringIO, Object]
|
@@ -62,6 +66,7 @@ module Lithic
|
|
62
66
|
exactness[:yes] += 1
|
63
67
|
value
|
64
68
|
else
|
69
|
+
state[:error] = TypeError.new("#{value.class} can't be coerced into #{StringIO}")
|
65
70
|
exactness[:no] += 1
|
66
71
|
value
|
67
72
|
end
|
@@ -77,10 +77,14 @@ module Lithic
|
|
77
77
|
#
|
78
78
|
# @param state [Hash{Symbol=>Object}] .
|
79
79
|
#
|
80
|
-
# @option state [Boolean
|
80
|
+
# @option state [Boolean] :translate_names
|
81
|
+
#
|
82
|
+
# @option state [Boolean] :strictness
|
81
83
|
#
|
82
84
|
# @option state [Hash{Symbol=>Object}] :exactness
|
83
85
|
#
|
86
|
+
# @option state [Class<StandardError>] :error
|
87
|
+
#
|
84
88
|
# @option state [Integer] :branched
|
85
89
|
#
|
86
90
|
# @return [Hash{Symbol=>Object}, Object]
|
@@ -89,6 +93,7 @@ module Lithic
|
|
89
93
|
|
90
94
|
unless value.is_a?(Hash)
|
91
95
|
exactness[:no] += 1
|
96
|
+
state[:error] = TypeError.new("#{value.class} can't be coerced into #{Hash}")
|
92
97
|
return value
|
93
98
|
end
|
94
99
|
|
@@ -126,14 +126,23 @@ module Lithic
|
|
126
126
|
|
127
127
|
# @api private
|
128
128
|
#
|
129
|
+
# Tries to efficiently coerce the given value to one of the known variants.
|
130
|
+
#
|
131
|
+
# If the value cannot match any of the known variants, the coercion is considered
|
132
|
+
# non-viable and returns the original value.
|
133
|
+
#
|
129
134
|
# @param value [Object]
|
130
135
|
#
|
131
136
|
# @param state [Hash{Symbol=>Object}] .
|
132
137
|
#
|
133
|
-
# @option state [Boolean
|
138
|
+
# @option state [Boolean] :translate_names
|
139
|
+
#
|
140
|
+
# @option state [Boolean] :strictness
|
134
141
|
#
|
135
142
|
# @option state [Hash{Symbol=>Object}] :exactness
|
136
143
|
#
|
144
|
+
# @option state [Class<StandardError>] :error
|
145
|
+
#
|
137
146
|
# @option state [Integer] :branched
|
138
147
|
#
|
139
148
|
# @return [Object]
|
@@ -144,7 +153,6 @@ module Lithic
|
|
144
153
|
|
145
154
|
strictness = state.fetch(:strictness)
|
146
155
|
exactness = state.fetch(:exactness)
|
147
|
-
state[:strictness] = strictness == :strong ? true : strictness
|
148
156
|
|
149
157
|
alternatives = []
|
150
158
|
known_variants.each do |_, variant_fn|
|
@@ -163,13 +171,10 @@ module Lithic
|
|
163
171
|
end
|
164
172
|
end
|
165
173
|
|
166
|
-
case alternatives.sort_by(&:first)
|
174
|
+
case alternatives.sort_by!(&:first)
|
167
175
|
in []
|
168
176
|
exactness[:no] += 1
|
169
|
-
|
170
|
-
message = "no possible conversion of #{value.class} into a variant of #{target.inspect}"
|
171
|
-
raise ArgumentError.new(message)
|
172
|
-
end
|
177
|
+
state[:error] = ArgumentError.new("no matching variant for #{value.inspect}")
|
173
178
|
value
|
174
179
|
in [[_, exact, coerced], *]
|
175
180
|
exact.each { exactness[_1] += _2 }
|
@@ -33,14 +33,20 @@ module Lithic
|
|
33
33
|
class << self
|
34
34
|
# @api private
|
35
35
|
#
|
36
|
+
# No coercion needed for Unknown type.
|
37
|
+
#
|
36
38
|
# @param value [Object]
|
37
39
|
#
|
38
40
|
# @param state [Hash{Symbol=>Object}] .
|
39
41
|
#
|
40
|
-
# @option state [Boolean
|
42
|
+
# @option state [Boolean] :translate_names
|
43
|
+
#
|
44
|
+
# @option state [Boolean] :strictness
|
41
45
|
#
|
42
46
|
# @option state [Hash{Symbol=>Object}] :exactness
|
43
47
|
#
|
48
|
+
# @option state [Class<StandardError>] :error
|
49
|
+
#
|
44
50
|
# @option state [Integer] :branched
|
45
51
|
#
|
46
52
|
# @return [Object]
|