modern_treasury 0.1.0.pre.alpha.17 → 0.1.0.pre.alpha.18
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/.ignore +2 -0
- data/CHANGELOG.md +635 -0
- data/README.md +37 -12
- data/SECURITY.md +27 -0
- data/lib/modern_treasury/client.rb +3 -2
- data/lib/modern_treasury/internal/page.rb +27 -23
- data/lib/modern_treasury/internal/transport/base_client.rb +19 -5
- data/lib/modern_treasury/internal/transport/pooled_net_requester.rb +20 -7
- data/lib/modern_treasury/internal/type/array_of.rb +23 -4
- data/lib/modern_treasury/internal/type/base_model.rb +45 -10
- data/lib/modern_treasury/internal/type/base_page.rb +1 -0
- data/lib/modern_treasury/internal/type/boolean.rb +7 -1
- data/lib/modern_treasury/internal/type/converter.rb +66 -17
- data/lib/modern_treasury/internal/type/enum.rb +24 -4
- data/lib/modern_treasury/internal/type/hash_of.rb +23 -4
- data/lib/modern_treasury/internal/type/io_like.rb +77 -0
- data/lib/modern_treasury/internal/type/request_parameters.rb +11 -2
- data/lib/modern_treasury/internal/type/union.rb +30 -6
- data/lib/modern_treasury/internal/type/unknown.rb +7 -1
- data/lib/modern_treasury/internal/util.rb +115 -29
- data/lib/modern_treasury/internal.rb +5 -1
- data/lib/modern_treasury/models/document_create_params.rb +3 -3
- data/lib/modern_treasury/models/payment_order_create_params.rb +3 -3
- data/lib/modern_treasury/resources/documents.rb +1 -1
- data/lib/modern_treasury/version.rb +1 -1
- data/lib/modern_treasury.rb +1 -0
- data/rbi/lib/modern_treasury/client.rbi +3 -2
- data/rbi/lib/modern_treasury/internal/page.rbi +1 -0
- data/rbi/lib/modern_treasury/internal/transport/base_client.rbi +1 -0
- data/rbi/lib/modern_treasury/internal/transport/pooled_net_requester.rbi +1 -1
- data/rbi/lib/modern_treasury/internal/type/array_of.rbi +18 -12
- data/rbi/lib/modern_treasury/internal/type/base_model.rbi +13 -3
- data/rbi/lib/modern_treasury/internal/type/boolean.rbi +16 -12
- data/rbi/lib/modern_treasury/internal/type/converter.rbi +24 -8
- data/rbi/lib/modern_treasury/internal/type/enum.rbi +15 -5
- data/rbi/lib/modern_treasury/internal/type/hash_of.rbi +18 -12
- data/rbi/lib/modern_treasury/internal/type/io_like.rbi +46 -0
- data/rbi/lib/modern_treasury/internal/type/union.rbi +11 -3
- data/rbi/lib/modern_treasury/internal/type/unknown.rbi +10 -7
- data/rbi/lib/modern_treasury/internal/util.rbi +50 -4
- data/rbi/lib/modern_treasury/internal.rbi +1 -1
- data/rbi/lib/modern_treasury/models/document_create_params.rbi +3 -3
- data/rbi/lib/modern_treasury/models/payment_order_create_params.rbi +3 -3
- data/rbi/lib/modern_treasury/resources/documents.rbi +1 -1
- data/sig/modern_treasury/internal/transport/pooled_net_requester.rbs +1 -1
- data/sig/modern_treasury/internal/type/array_of.rbs +7 -2
- data/sig/modern_treasury/internal/type/base_model.rbs +7 -2
- data/sig/modern_treasury/internal/type/boolean.rbs +5 -2
- data/sig/modern_treasury/internal/type/converter.rbs +15 -5
- data/sig/modern_treasury/internal/type/enum.rbs +7 -2
- data/sig/modern_treasury/internal/type/hash_of.rbs +7 -2
- data/sig/modern_treasury/internal/type/io_like.rbs +23 -0
- data/sig/modern_treasury/internal/type/union.rbs +7 -2
- data/sig/modern_treasury/internal/type/unknown.rbs +5 -2
- data/sig/modern_treasury/internal/util.rbs +19 -2
- data/sig/modern_treasury/internal.rbs +1 -1
- data/sig/modern_treasury/models/document_create_params.rbs +3 -3
- data/sig/modern_treasury/models/payment_order_create_params.rbs +3 -3
- data/sig/modern_treasury/resources/documents.rbs +1 -1
- metadata +8 -2
data/README.md
CHANGED
@@ -4,9 +4,9 @@ The Modern Treasury Ruby library provides convenient access to the Modern Treasu
|
|
4
4
|
|
5
5
|
## Documentation
|
6
6
|
|
7
|
-
Documentation for
|
7
|
+
Documentation for releases of this gem can be found [on RubyDoc](https://gemdocs.org/gems/modern_treasury).
|
8
8
|
|
9
|
-
The
|
9
|
+
The REST API documentation can be found on [docs.moderntreasury.com](https://docs.moderntreasury.com).
|
10
10
|
|
11
11
|
## Installation
|
12
12
|
|
@@ -15,17 +15,11 @@ 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 "modern_treasury", "~> 0.1.0.pre.alpha.
|
18
|
+
gem "modern_treasury", "~> 0.1.0.pre.alpha.18"
|
19
19
|
```
|
20
20
|
|
21
21
|
<!-- x-release-please-end -->
|
22
22
|
|
23
|
-
To fetch an initial copy of the gem:
|
24
|
-
|
25
|
-
```sh
|
26
|
-
bundle install
|
27
|
-
```
|
28
|
-
|
29
23
|
## Usage
|
30
24
|
|
31
25
|
```ruby
|
@@ -61,9 +55,34 @@ page.auto_paging_each do |counterparty|
|
|
61
55
|
end
|
62
56
|
```
|
63
57
|
|
58
|
+
### File uploads
|
59
|
+
|
60
|
+
Request parameters that correspond to file uploads can be passed as `StringIO`, or a [`Pathname`](https://rubyapi.org/3.1/o/pathname) instance.
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
require "pathname"
|
64
|
+
|
65
|
+
# using `Pathname`, the file will be lazily read, without reading everything in to memory
|
66
|
+
document = modern_treasury.documents.create(
|
67
|
+
documentable_id: "24c6b7a3-02...",
|
68
|
+
documentable_type: "counterparties",
|
69
|
+
file: Pathname("my/file.txt")
|
70
|
+
)
|
71
|
+
|
72
|
+
file = File.read("my/file.txt")
|
73
|
+
# using `StringIO`, useful if you already have the data in memory
|
74
|
+
document = modern_treasury.documents.create(
|
75
|
+
documentable_id: "24c6b7a3-02...",
|
76
|
+
documentable_type: "counterparties",
|
77
|
+
file: StringIO.new(file)
|
78
|
+
)
|
79
|
+
|
80
|
+
puts(document.id)
|
81
|
+
```
|
82
|
+
|
64
83
|
### Errors
|
65
84
|
|
66
|
-
When the library is unable to connect to the API, or if the API returns a non-success status code (i.e., 4xx or 5xx response), a subclass of `ModernTreasury::
|
85
|
+
When the library is unable to connect to the API, or if the API returns a non-success status code (i.e., 4xx or 5xx response), a subclass of `ModernTreasury::Errors::APIError` will be thrown:
|
67
86
|
|
68
87
|
```ruby
|
69
88
|
begin
|
@@ -141,6 +160,13 @@ After Solargraph is installed, **you must populate its index** either via the pr
|
|
141
160
|
bundle exec solargraph gems
|
142
161
|
```
|
143
162
|
|
163
|
+
Note: if you had installed the gem either using a `git:` or `github:` URL, or had vendored the gem using bundler, you will need to set up your [`.solargraph.yml`](https://solargraph.org/guides/configuration) to include the path to the gem's `lib` directory.
|
164
|
+
|
165
|
+
```yaml
|
166
|
+
include:
|
167
|
+
- 'vendor/bundle/ruby/*/gems/modern_treasury-*/lib/**/*.rb'
|
168
|
+
```
|
169
|
+
|
144
170
|
Otherwise Solargraph will not be able to provide type information or auto-completion for any non-indexed libraries.
|
145
171
|
|
146
172
|
### Sorbet
|
@@ -182,8 +208,7 @@ If you want to explicitly send an extra param, you can do so with the `extra_que
|
|
182
208
|
To make requests to undocumented endpoints, you can make requests using `client.request`. Options on the client will be respected (such as retries) when making this request.
|
183
209
|
|
184
210
|
```ruby
|
185
|
-
response =
|
186
|
-
client.request(
|
211
|
+
response = client.request(
|
187
212
|
method: :post,
|
188
213
|
path: '/undocumented/endpoint',
|
189
214
|
query: {"dog": "woof"},
|
data/SECURITY.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Security Policy
|
2
|
+
|
3
|
+
## Reporting Security Issues
|
4
|
+
|
5
|
+
This SDK is generated by [Stainless Software Inc](http://stainless.com). Stainless takes security seriously, and encourages you to report any security vulnerability promptly so that appropriate action can be taken.
|
6
|
+
|
7
|
+
To report a security issue, please contact the Stainless team at security@stainless.com.
|
8
|
+
|
9
|
+
## Responsible Disclosure
|
10
|
+
|
11
|
+
We appreciate the efforts of security researchers and individuals who help us maintain the security of
|
12
|
+
SDKs we generate. If you believe you have found a security vulnerability, please adhere to responsible
|
13
|
+
disclosure practices by allowing us a reasonable amount of time to investigate and address the issue
|
14
|
+
before making any information public.
|
15
|
+
|
16
|
+
## Reporting Non-SDK Related Security Issues
|
17
|
+
|
18
|
+
If you encounter security issues that are not directly related to SDKs but pertain to the services
|
19
|
+
or products provided by Modern Treasury please follow the respective company's security reporting guidelines.
|
20
|
+
|
21
|
+
### Modern Treasury Terms and Policies
|
22
|
+
|
23
|
+
Please contact sdk-feedback@moderntreasury.com for any questions or concerns regarding security of our services.
|
24
|
+
|
25
|
+
---
|
26
|
+
|
27
|
+
Thank you for helping us keep the SDKs and systems they interact with secure.
|
@@ -167,7 +167,8 @@ module ModernTreasury
|
|
167
167
|
#
|
168
168
|
# @param organization_id [String, nil] Defaults to `ENV["MODERN_TREASURY_ORGANIZATION_ID"]`
|
169
169
|
#
|
170
|
-
# @param base_url [String, nil] Override the default base URL for the API, e.g.,
|
170
|
+
# @param base_url [String, nil] Override the default base URL for the API, e.g.,
|
171
|
+
# `"https://api.example.com/v2/"`. Defaults to `ENV["MODERN_TREASURY_BASE_URL"]`
|
171
172
|
#
|
172
173
|
# @param max_retries [Integer] Max number of retries to attempt after a failed retryable request.
|
173
174
|
#
|
@@ -181,7 +182,7 @@ module ModernTreasury
|
|
181
182
|
def initialize(
|
182
183
|
api_key: ENV["MODERN_TREASURY_API_KEY"],
|
183
184
|
organization_id: ENV["MODERN_TREASURY_ORGANIZATION_ID"],
|
184
|
-
base_url:
|
185
|
+
base_url: ENV["MODERN_TREASURY_BASE_URL"],
|
185
186
|
max_retries: DEFAULT_MAX_RETRIES,
|
186
187
|
timeout: DEFAULT_TIMEOUT_IN_SECONDS,
|
187
188
|
initial_retry_delay: DEFAULT_INITIAL_RETRY_DELAY,
|
@@ -22,27 +22,6 @@ module ModernTreasury
|
|
22
22
|
# @return [String]
|
23
23
|
attr_accessor :after_cursor
|
24
24
|
|
25
|
-
# @api private
|
26
|
-
#
|
27
|
-
# @param client [ModernTreasury::Internal::Transport::BaseClient]
|
28
|
-
# @param req [Hash{Symbol=>Object}]
|
29
|
-
# @param headers [Hash{String=>String}, Net::HTTPHeader]
|
30
|
-
# @param page_data [Hash{Symbol=>Object}]
|
31
|
-
def initialize(client:, req:, headers:, page_data:)
|
32
|
-
super
|
33
|
-
model = req.fetch(:model)
|
34
|
-
|
35
|
-
case page_data
|
36
|
-
in Array
|
37
|
-
replace(page_data.map { ModernTreasury::Internal::Type::Converter.coerce(model, _1) })
|
38
|
-
else
|
39
|
-
end
|
40
|
-
|
41
|
-
@per_page = ModernTreasury::Internal::Util.coerce_integer(headers["X-Per-Page"])
|
42
|
-
|
43
|
-
@after_cursor = headers["X-After-Cursor"]&.to_s
|
44
|
-
end
|
45
|
-
|
46
25
|
# @return [Boolean]
|
47
26
|
def next_page?
|
48
27
|
!after_cursor.nil?
|
@@ -67,18 +46,43 @@ module ModernTreasury
|
|
67
46
|
unless block_given?
|
68
47
|
raise ArgumentError.new("A block must be given to ##{__method__}")
|
69
48
|
end
|
49
|
+
|
70
50
|
page = self
|
71
51
|
loop do
|
72
|
-
page.each
|
52
|
+
page.each(&blk)
|
53
|
+
|
73
54
|
break unless page.next_page?
|
74
55
|
page = page.next_page
|
75
56
|
end
|
76
57
|
end
|
77
58
|
|
59
|
+
# @api private
|
60
|
+
#
|
61
|
+
# @param client [ModernTreasury::Internal::Transport::BaseClient]
|
62
|
+
# @param req [Hash{Symbol=>Object}]
|
63
|
+
# @param headers [Hash{String=>String}, Net::HTTPHeader]
|
64
|
+
# @param page_data [Hash{Symbol=>Object}]
|
65
|
+
def initialize(client:, req:, headers:, page_data:)
|
66
|
+
super
|
67
|
+
|
68
|
+
case page_data
|
69
|
+
in Array
|
70
|
+
replace(page_data.map { ModernTreasury::Internal::Type::Converter.coerce(@model, _1) })
|
71
|
+
else
|
72
|
+
end
|
73
|
+
|
74
|
+
@per_page = ModernTreasury::Internal::Util.coerce_integer(headers["X-Per-Page"])
|
75
|
+
@after_cursor = headers["X-After-Cursor"]&.to_s
|
76
|
+
end
|
77
|
+
|
78
|
+
# @api private
|
79
|
+
#
|
78
80
|
# @return [String]
|
79
81
|
def inspect
|
80
82
|
# rubocop:disable Layout/LineLength
|
81
|
-
|
83
|
+
model = ModernTreasury::Internal::Type::Converter.inspect(@model, depth: 1)
|
84
|
+
|
85
|
+
"#<#{self.class}[#{model}]:0x#{object_id.to_s(16)} per_page=#{per_page.inspect} after_cursor=#{after_cursor.inspect}>"
|
82
86
|
# rubocop:enable Layout/LineLength
|
83
87
|
end
|
84
88
|
end
|
@@ -93,7 +93,11 @@ module ModernTreasury
|
|
93
93
|
URI.join(url, response_headers["location"])
|
94
94
|
rescue ArgumentError
|
95
95
|
message = "Server responded with status #{status} but no valid location header."
|
96
|
-
raise ModernTreasury::Errors::APIConnectionError.new(
|
96
|
+
raise ModernTreasury::Errors::APIConnectionError.new(
|
97
|
+
url: url,
|
98
|
+
response: response_headers,
|
99
|
+
message: message
|
100
|
+
)
|
97
101
|
end
|
98
102
|
|
99
103
|
request = {**request, url: location}
|
@@ -101,7 +105,11 @@ module ModernTreasury
|
|
101
105
|
case [url.scheme, location.scheme]
|
102
106
|
in ["https", "http"]
|
103
107
|
message = "Tried to redirect to a insecure URL"
|
104
|
-
raise ModernTreasury::Errors::APIConnectionError.new(
|
108
|
+
raise ModernTreasury::Errors::APIConnectionError.new(
|
109
|
+
url: url,
|
110
|
+
response: response_headers,
|
111
|
+
message: message
|
112
|
+
)
|
105
113
|
else
|
106
114
|
nil
|
107
115
|
end
|
@@ -245,7 +253,7 @@ module ModernTreasury
|
|
245
253
|
|
246
254
|
if @idempotency_header &&
|
247
255
|
!headers.key?(@idempotency_header) &&
|
248
|
-
!Net::HTTP::IDEMPOTENT_METHODS_.include?(method.to_s.upcase)
|
256
|
+
(!Net::HTTP::IDEMPOTENT_METHODS_.include?(method.to_s.upcase) || opts.key?(:idempotency_key))
|
249
257
|
headers[@idempotency_header] = opts.fetch(:idempotency_key) { generate_idempotency_key }
|
250
258
|
end
|
251
259
|
|
@@ -353,7 +361,11 @@ module ModernTreasury
|
|
353
361
|
self.class.reap_connection!(status, stream: stream)
|
354
362
|
|
355
363
|
message = "Failed to complete the request within #{self.class::MAX_REDIRECTS} redirects."
|
356
|
-
raise ModernTreasury::Errors::APIConnectionError.new(
|
364
|
+
raise ModernTreasury::Errors::APIConnectionError.new(
|
365
|
+
url: url,
|
366
|
+
response: response,
|
367
|
+
message: message
|
368
|
+
)
|
357
369
|
in 300..399
|
358
370
|
self.class.reap_connection!(status, stream: stream)
|
359
371
|
|
@@ -383,7 +395,7 @@ module ModernTreasury
|
|
383
395
|
in (400..) | ModernTreasury::Errors::APIConnectionError
|
384
396
|
self.class.reap_connection!(status, stream: stream)
|
385
397
|
|
386
|
-
delay = retry_delay(response, retry_count: retry_count)
|
398
|
+
delay = retry_delay(response || {}, retry_count: retry_count)
|
387
399
|
sleep(delay)
|
388
400
|
|
389
401
|
send_request(
|
@@ -463,6 +475,8 @@ module ModernTreasury
|
|
463
475
|
end
|
464
476
|
end
|
465
477
|
|
478
|
+
# @api private
|
479
|
+
#
|
466
480
|
# @return [String]
|
467
481
|
def inspect
|
468
482
|
# rubocop:disable Layout/LineLength
|
@@ -54,14 +54,18 @@ module ModernTreasury
|
|
54
54
|
# @param blk [Proc]
|
55
55
|
#
|
56
56
|
# @yieldparam [String]
|
57
|
-
# @return [Net::HTTPGenericRequest]
|
57
|
+
# @return [Array(Net::HTTPGenericRequest, Proc)]
|
58
58
|
def build_request(request, &blk)
|
59
59
|
method, url, headers, body = request.fetch_values(:method, :url, :headers, :body)
|
60
|
+
|
61
|
+
# ensure we construct a URI class of the right scheme
|
62
|
+
url = URI(url.to_s)
|
63
|
+
|
60
64
|
req = Net::HTTPGenericRequest.new(
|
61
65
|
method.to_s.upcase,
|
62
66
|
!body.nil?,
|
63
67
|
method != :head,
|
64
|
-
url
|
68
|
+
url
|
65
69
|
)
|
66
70
|
|
67
71
|
headers.each { req[_1] = _2 }
|
@@ -75,12 +79,12 @@ module ModernTreasury
|
|
75
79
|
in StringIO
|
76
80
|
req["content-length"] ||= body.size.to_s unless req["transfer-encoding"]
|
77
81
|
req.body_stream = ModernTreasury::Internal::Util::ReadIOAdapter.new(body, &blk)
|
78
|
-
in IO | Enumerator
|
82
|
+
in Pathname | IO | Enumerator
|
79
83
|
req["transfer-encoding"] ||= "chunked" unless req["content-length"]
|
80
84
|
req.body_stream = ModernTreasury::Internal::Util::ReadIOAdapter.new(body, &blk)
|
81
85
|
end
|
82
86
|
|
83
|
-
req
|
87
|
+
[req, req.body_stream&.method(:close)]
|
84
88
|
end
|
85
89
|
end
|
86
90
|
|
@@ -123,13 +127,17 @@ module ModernTreasury
|
|
123
127
|
def execute(request)
|
124
128
|
url, deadline = request.fetch_values(:url, :deadline)
|
125
129
|
|
130
|
+
req = nil
|
126
131
|
eof = false
|
127
132
|
finished = false
|
133
|
+
closing = nil
|
134
|
+
|
135
|
+
# rubocop:disable Metrics/BlockLength
|
128
136
|
enum = Enumerator.new do |y|
|
129
137
|
with_pool(url, deadline: deadline) do |conn|
|
130
138
|
next if finished
|
131
139
|
|
132
|
-
req = self.class.build_request(request) do
|
140
|
+
req, closing = self.class.build_request(request) do
|
133
141
|
self.class.calibrate_socket_timeout(conn, deadline)
|
134
142
|
end
|
135
143
|
|
@@ -145,7 +153,7 @@ module ModernTreasury
|
|
145
153
|
break if finished
|
146
154
|
|
147
155
|
rsp.read_body do |bytes|
|
148
|
-
y << bytes
|
156
|
+
y << bytes.force_encoding(Encoding::BINARY)
|
149
157
|
break if finished
|
150
158
|
|
151
159
|
self.class.calibrate_socket_timeout(conn, deadline)
|
@@ -154,8 +162,11 @@ module ModernTreasury
|
|
154
162
|
end
|
155
163
|
end
|
156
164
|
rescue Timeout::Error
|
157
|
-
raise ModernTreasury::Errors::APITimeoutError
|
165
|
+
raise ModernTreasury::Errors::APITimeoutError.new(url: url, request: req)
|
166
|
+
rescue StandardError
|
167
|
+
raise ModernTreasury::Errors::APIConnectionError.new(url: url, request: req)
|
158
168
|
end
|
169
|
+
# rubocop:enable Metrics/BlockLength
|
159
170
|
|
160
171
|
conn, _, response = enum.next
|
161
172
|
body = ModernTreasury::Internal::Util.fused_enum(enum, external: true) do
|
@@ -165,7 +176,9 @@ module ModernTreasury
|
|
165
176
|
rescue StopIteration
|
166
177
|
nil
|
167
178
|
end
|
179
|
+
ensure
|
168
180
|
conn.finish if !eof && conn&.started?
|
181
|
+
closing&.call
|
169
182
|
end
|
170
183
|
[Integer(response.code), response, (response.body = body)]
|
171
184
|
end
|
@@ -13,6 +13,10 @@ module ModernTreasury
|
|
13
13
|
class ArrayOf
|
14
14
|
include ModernTreasury::Internal::Type::Converter
|
15
15
|
|
16
|
+
private_class_method :new
|
17
|
+
|
18
|
+
# @overload [](type_info, spec = {})
|
19
|
+
#
|
16
20
|
# @param type_info [Hash{Symbol=>Object}, Proc, ModernTreasury::Internal::Type::Converter, Class]
|
17
21
|
#
|
18
22
|
# @param spec [Hash{Symbol=>Object}] .
|
@@ -24,7 +28,7 @@ module ModernTreasury
|
|
24
28
|
# @option spec [Proc] :union
|
25
29
|
#
|
26
30
|
# @option spec [Boolean] :"nil?"
|
27
|
-
def self.[](
|
31
|
+
def self.[](...) = new(...)
|
28
32
|
|
29
33
|
# @param other [Object]
|
30
34
|
#
|
@@ -79,12 +83,16 @@ module ModernTreasury
|
|
79
83
|
#
|
80
84
|
# @param value [Array<Object>, Object]
|
81
85
|
#
|
86
|
+
# @param state [Hash{Symbol=>Object}] .
|
87
|
+
#
|
88
|
+
# @option state [Boolean] :can_retry
|
89
|
+
#
|
82
90
|
# @return [Array<Object>, Object]
|
83
|
-
def dump(value)
|
91
|
+
def dump(value, state:)
|
84
92
|
target = item_type
|
85
93
|
if value.is_a?(Array)
|
86
94
|
value.map do
|
87
|
-
ModernTreasury::Internal::Type::Converter.dump(target, _1)
|
95
|
+
ModernTreasury::Internal::Type::Converter.dump(target, _1, state: state)
|
88
96
|
end
|
89
97
|
else
|
90
98
|
super
|
@@ -116,7 +124,18 @@ module ModernTreasury
|
|
116
124
|
# @option spec [Boolean] :"nil?"
|
117
125
|
def initialize(type_info, spec = {})
|
118
126
|
@item_type_fn = ModernTreasury::Internal::Type::Converter.type_info(type_info || spec)
|
119
|
-
@nilable = spec
|
127
|
+
@nilable = spec.fetch(:nil?, false)
|
128
|
+
end
|
129
|
+
|
130
|
+
# @api private
|
131
|
+
#
|
132
|
+
# @param depth [Integer]
|
133
|
+
#
|
134
|
+
# @return [String]
|
135
|
+
def inspect(depth: 0)
|
136
|
+
items = ModernTreasury::Internal::Type::Converter.inspect(item_type, depth: depth.succ)
|
137
|
+
|
138
|
+
"#{self.class}[#{[items, nilable? ? 'nil' : nil].compact.join(' | ')}]"
|
120
139
|
end
|
121
140
|
end
|
122
141
|
end
|
@@ -62,7 +62,7 @@ module ModernTreasury
|
|
62
62
|
|
63
63
|
setter = "#{name_sym}="
|
64
64
|
api_name = info.fetch(:api_name, name_sym)
|
65
|
-
nilable = info
|
65
|
+
nilable = info.fetch(:nil?, false)
|
66
66
|
const = if required && !nilable
|
67
67
|
info.fetch(
|
68
68
|
:const,
|
@@ -256,8 +256,12 @@ module ModernTreasury
|
|
256
256
|
#
|
257
257
|
# @param value [ModernTreasury::Internal::Type::BaseModel, Object]
|
258
258
|
#
|
259
|
+
# @param state [Hash{Symbol=>Object}] .
|
260
|
+
#
|
261
|
+
# @option state [Boolean] :can_retry
|
262
|
+
#
|
259
263
|
# @return [Hash{Object=>Object}, Object]
|
260
|
-
def dump(value)
|
264
|
+
def dump(value, state:)
|
261
265
|
unless (coerced = ModernTreasury::Internal::Util.coerce_hash(value)).is_a?(Hash)
|
262
266
|
return super
|
263
267
|
end
|
@@ -268,7 +272,7 @@ module ModernTreasury
|
|
268
272
|
name = key.is_a?(String) ? key.to_sym : key
|
269
273
|
case (field = known_fields[name])
|
270
274
|
in nil
|
271
|
-
acc.store(name, super(val))
|
275
|
+
acc.store(name, super(val, state: state))
|
272
276
|
else
|
273
277
|
api_name, mode, type_fn = field.fetch_values(:api_name, :mode, :type_fn)
|
274
278
|
case mode
|
@@ -276,7 +280,10 @@ module ModernTreasury
|
|
276
280
|
next
|
277
281
|
else
|
278
282
|
target = type_fn.call
|
279
|
-
acc.store(
|
283
|
+
acc.store(
|
284
|
+
api_name,
|
285
|
+
ModernTreasury::Internal::Type::Converter.dump(target, val, state: state)
|
286
|
+
)
|
280
287
|
end
|
281
288
|
end
|
282
289
|
end
|
@@ -341,12 +348,12 @@ module ModernTreasury
|
|
341
348
|
# @param a [Object]
|
342
349
|
#
|
343
350
|
# @return [String]
|
344
|
-
def to_json(*a) =
|
351
|
+
def to_json(*a) = ModernTreasury::Internal::Type::Converter.dump(self.class, self).to_json(*a)
|
345
352
|
|
346
353
|
# @param a [Object]
|
347
354
|
#
|
348
355
|
# @return [String]
|
349
|
-
def to_yaml(*a) =
|
356
|
+
def to_yaml(*a) = ModernTreasury::Internal::Type::Converter.dump(self.class, self).to_yaml(*a)
|
350
357
|
|
351
358
|
# Create a new instance of a model.
|
352
359
|
#
|
@@ -361,14 +368,42 @@ module ModernTreasury
|
|
361
368
|
end
|
362
369
|
end
|
363
370
|
|
371
|
+
class << self
|
372
|
+
# @api private
|
373
|
+
#
|
374
|
+
# @param depth [Integer]
|
375
|
+
#
|
376
|
+
# @return [String]
|
377
|
+
def inspect(depth: 0)
|
378
|
+
return super() if depth.positive?
|
379
|
+
|
380
|
+
depth = depth.succ
|
381
|
+
deferred = fields.transform_values do |field|
|
382
|
+
type, required, nilable = field.fetch_values(:type, :required, :nilable)
|
383
|
+
-> do
|
384
|
+
[
|
385
|
+
ModernTreasury::Internal::Type::Converter.inspect(type, depth: depth),
|
386
|
+
!required || nilable ? "nil" : nil
|
387
|
+
].compact.join(" | ")
|
388
|
+
end
|
389
|
+
.tap { _1.define_singleton_method(:inspect) { call } }
|
390
|
+
end
|
391
|
+
|
392
|
+
"#{name}[#{deferred.inspect}]"
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
# @api private
|
397
|
+
#
|
364
398
|
# @return [String]
|
365
399
|
def inspect
|
366
|
-
rows =
|
367
|
-
"#{_1}=#{
|
400
|
+
rows = @data.map do
|
401
|
+
"#{_1}=#{self.class.known_fields.key?(_1) ? public_send(_1).inspect : ''}"
|
368
402
|
rescue ModernTreasury::Errors::ConversionError
|
369
|
-
"#{_1}=#{
|
403
|
+
"#{_1}=#{_2.inspect}"
|
370
404
|
end
|
371
|
-
|
405
|
+
|
406
|
+
"#<#{self.class}:0x#{object_id.to_s(16)} #{rows.join(' ')}>"
|
372
407
|
end
|
373
408
|
end
|
374
409
|
end
|
@@ -11,6 +11,8 @@ module ModernTreasury
|
|
11
11
|
class Boolean
|
12
12
|
extend ModernTreasury::Internal::Type::Converter
|
13
13
|
|
14
|
+
private_class_method :new
|
15
|
+
|
14
16
|
# @param other [Object]
|
15
17
|
#
|
16
18
|
# @return [Boolean]
|
@@ -45,8 +47,12 @@ module ModernTreasury
|
|
45
47
|
# #
|
46
48
|
# # @param value [Boolean, Object]
|
47
49
|
# #
|
50
|
+
# # @param state [Hash{Symbol=>Object}] .
|
51
|
+
# #
|
52
|
+
# # @option state [Boolean] :can_retry
|
53
|
+
# #
|
48
54
|
# # @return [Boolean, Object]
|
49
|
-
# def dump(value) = super
|
55
|
+
# def dump(value, state:) = super
|
50
56
|
end
|
51
57
|
end
|
52
58
|
end
|
@@ -26,20 +26,38 @@ module ModernTreasury
|
|
26
26
|
#
|
27
27
|
# @param value [Object]
|
28
28
|
#
|
29
|
+
# @param state [Hash{Symbol=>Object}] .
|
30
|
+
#
|
31
|
+
# @option state [Boolean] :can_retry
|
32
|
+
#
|
29
33
|
# @return [Object]
|
30
|
-
def dump(value)
|
34
|
+
def dump(value, state:)
|
31
35
|
case value
|
32
36
|
in Array
|
33
|
-
value.map { ModernTreasury::Internal::Type::Unknown.dump(_1) }
|
37
|
+
value.map { ModernTreasury::Internal::Type::Unknown.dump(_1, state: state) }
|
34
38
|
in Hash
|
35
|
-
value.transform_values { ModernTreasury::Internal::Type::Unknown.dump(_1) }
|
39
|
+
value.transform_values { ModernTreasury::Internal::Type::Unknown.dump(_1, state: state) }
|
36
40
|
in ModernTreasury::Internal::Type::BaseModel
|
37
|
-
value.class.dump(value)
|
41
|
+
value.class.dump(value, state: state)
|
42
|
+
in StringIO
|
43
|
+
value.string
|
44
|
+
in Pathname | IO
|
45
|
+
state[:can_retry] = false if value.is_a?(IO)
|
46
|
+
ModernTreasury::Internal::Util::SerializationAdapter.new(value)
|
38
47
|
else
|
39
48
|
value
|
40
49
|
end
|
41
50
|
end
|
42
51
|
|
52
|
+
# @api private
|
53
|
+
#
|
54
|
+
# @param depth [Integer]
|
55
|
+
#
|
56
|
+
# @return [String]
|
57
|
+
def inspect(depth: 0)
|
58
|
+
super()
|
59
|
+
end
|
60
|
+
|
43
61
|
# rubocop:enable Lint/UnusedMethodArgument
|
44
62
|
|
45
63
|
class << self
|
@@ -140,9 +158,9 @@ module ModernTreasury
|
|
140
158
|
if value.is_a?(Integer)
|
141
159
|
exactness[:yes] += 1
|
142
160
|
return value
|
143
|
-
elsif strictness == :strong
|
161
|
+
elsif strictness == :strong && Integer(value, exception: false) != value
|
144
162
|
message = "no implicit conversion of #{value.class} into #{target.inspect}"
|
145
|
-
raise TypeError.new(message)
|
163
|
+
raise value.is_a?(Numeric) ? ArgumentError.new(message) : TypeError.new(message)
|
146
164
|
else
|
147
165
|
Kernel.then do
|
148
166
|
return Integer(value).tap { exactness[:maybe] += 1 }
|
@@ -182,18 +200,26 @@ module ModernTreasury
|
|
182
200
|
rescue ArgumentError, TypeError => e
|
183
201
|
raise e if strictness == :strong
|
184
202
|
end
|
185
|
-
in -> { _1 <=
|
203
|
+
in -> { _1 <= StringIO } if value.is_a?(String)
|
186
204
|
exactness[:yes] += 1
|
187
205
|
return StringIO.new(value.b)
|
188
206
|
else
|
189
207
|
end
|
190
208
|
in Symbol
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
209
|
+
case value
|
210
|
+
in Symbol | String
|
211
|
+
if value.to_sym == target
|
212
|
+
exactness[:yes] += 1
|
213
|
+
return target
|
214
|
+
else
|
215
|
+
exactness[:maybe] += 1
|
216
|
+
return value
|
217
|
+
end
|
218
|
+
else
|
219
|
+
if strictness == :strong
|
220
|
+
message = "cannot convert non-matching #{value.class} into #{target.inspect}"
|
221
|
+
raise ArgumentError.new(message)
|
222
|
+
end
|
197
223
|
end
|
198
224
|
else
|
199
225
|
end
|
@@ -207,13 +233,36 @@ module ModernTreasury
|
|
207
233
|
# @api private
|
208
234
|
#
|
209
235
|
# @param target [ModernTreasury::Internal::Type::Converter, Class]
|
236
|
+
#
|
210
237
|
# @param value [Object]
|
211
238
|
#
|
239
|
+
# @param state [Hash{Symbol=>Object}] .
|
240
|
+
#
|
241
|
+
# @option state [Boolean] :can_retry
|
242
|
+
#
|
212
243
|
# @return [Object]
|
213
|
-
def dump(target, value)
|
214
|
-
|
215
|
-
|
216
|
-
|
244
|
+
def dump(target, value, state: {can_retry: true})
|
245
|
+
case target
|
246
|
+
in ModernTreasury::Internal::Type::Converter
|
247
|
+
target.dump(value, state: state)
|
248
|
+
else
|
249
|
+
ModernTreasury::Internal::Type::Unknown.dump(value, state: state)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
# @api private
|
254
|
+
#
|
255
|
+
# @param target [Object]
|
256
|
+
# @param depth [Integer]
|
257
|
+
#
|
258
|
+
# @return [String]
|
259
|
+
def inspect(target, depth:)
|
260
|
+
case target
|
261
|
+
in ModernTreasury::Internal::Type::Converter
|
262
|
+
target.inspect(depth: depth.succ)
|
263
|
+
else
|
264
|
+
target.inspect
|
265
|
+
end
|
217
266
|
end
|
218
267
|
end
|
219
268
|
end
|