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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.ignore +2 -0
  3. data/CHANGELOG.md +635 -0
  4. data/README.md +37 -12
  5. data/SECURITY.md +27 -0
  6. data/lib/modern_treasury/client.rb +3 -2
  7. data/lib/modern_treasury/internal/page.rb +27 -23
  8. data/lib/modern_treasury/internal/transport/base_client.rb +19 -5
  9. data/lib/modern_treasury/internal/transport/pooled_net_requester.rb +20 -7
  10. data/lib/modern_treasury/internal/type/array_of.rb +23 -4
  11. data/lib/modern_treasury/internal/type/base_model.rb +45 -10
  12. data/lib/modern_treasury/internal/type/base_page.rb +1 -0
  13. data/lib/modern_treasury/internal/type/boolean.rb +7 -1
  14. data/lib/modern_treasury/internal/type/converter.rb +66 -17
  15. data/lib/modern_treasury/internal/type/enum.rb +24 -4
  16. data/lib/modern_treasury/internal/type/hash_of.rb +23 -4
  17. data/lib/modern_treasury/internal/type/io_like.rb +77 -0
  18. data/lib/modern_treasury/internal/type/request_parameters.rb +11 -2
  19. data/lib/modern_treasury/internal/type/union.rb +30 -6
  20. data/lib/modern_treasury/internal/type/unknown.rb +7 -1
  21. data/lib/modern_treasury/internal/util.rb +115 -29
  22. data/lib/modern_treasury/internal.rb +5 -1
  23. data/lib/modern_treasury/models/document_create_params.rb +3 -3
  24. data/lib/modern_treasury/models/payment_order_create_params.rb +3 -3
  25. data/lib/modern_treasury/resources/documents.rb +1 -1
  26. data/lib/modern_treasury/version.rb +1 -1
  27. data/lib/modern_treasury.rb +1 -0
  28. data/rbi/lib/modern_treasury/client.rbi +3 -2
  29. data/rbi/lib/modern_treasury/internal/page.rbi +1 -0
  30. data/rbi/lib/modern_treasury/internal/transport/base_client.rbi +1 -0
  31. data/rbi/lib/modern_treasury/internal/transport/pooled_net_requester.rbi +1 -1
  32. data/rbi/lib/modern_treasury/internal/type/array_of.rbi +18 -12
  33. data/rbi/lib/modern_treasury/internal/type/base_model.rbi +13 -3
  34. data/rbi/lib/modern_treasury/internal/type/boolean.rbi +16 -12
  35. data/rbi/lib/modern_treasury/internal/type/converter.rbi +24 -8
  36. data/rbi/lib/modern_treasury/internal/type/enum.rbi +15 -5
  37. data/rbi/lib/modern_treasury/internal/type/hash_of.rbi +18 -12
  38. data/rbi/lib/modern_treasury/internal/type/io_like.rbi +46 -0
  39. data/rbi/lib/modern_treasury/internal/type/union.rbi +11 -3
  40. data/rbi/lib/modern_treasury/internal/type/unknown.rbi +10 -7
  41. data/rbi/lib/modern_treasury/internal/util.rbi +50 -4
  42. data/rbi/lib/modern_treasury/internal.rbi +1 -1
  43. data/rbi/lib/modern_treasury/models/document_create_params.rbi +3 -3
  44. data/rbi/lib/modern_treasury/models/payment_order_create_params.rbi +3 -3
  45. data/rbi/lib/modern_treasury/resources/documents.rbi +1 -1
  46. data/sig/modern_treasury/internal/transport/pooled_net_requester.rbs +1 -1
  47. data/sig/modern_treasury/internal/type/array_of.rbs +7 -2
  48. data/sig/modern_treasury/internal/type/base_model.rbs +7 -2
  49. data/sig/modern_treasury/internal/type/boolean.rbs +5 -2
  50. data/sig/modern_treasury/internal/type/converter.rbs +15 -5
  51. data/sig/modern_treasury/internal/type/enum.rbs +7 -2
  52. data/sig/modern_treasury/internal/type/hash_of.rbs +7 -2
  53. data/sig/modern_treasury/internal/type/io_like.rbs +23 -0
  54. data/sig/modern_treasury/internal/type/union.rbs +7 -2
  55. data/sig/modern_treasury/internal/type/unknown.rbs +5 -2
  56. data/sig/modern_treasury/internal/util.rbs +19 -2
  57. data/sig/modern_treasury/internal.rbs +1 -1
  58. data/sig/modern_treasury/models/document_create_params.rbs +3 -3
  59. data/sig/modern_treasury/models/payment_order_create_params.rbs +3 -3
  60. data/sig/modern_treasury/resources/documents.rbs +1 -1
  61. metadata +8 -2
@@ -58,9 +58,9 @@ module ModernTreasury
58
58
  #
59
59
  # @return [Boolean]
60
60
  def ==(other)
61
- # rubocop:disable Layout/LineLength
62
- other.is_a?(Module) && other.singleton_class <= ModernTreasury::Internal::Type::Enum && other.values.to_set == values.to_set
63
- # rubocop:enable Layout/LineLength
61
+ # rubocop:disable Style/CaseEquality
62
+ ModernTreasury::Internal::Type::Enum === other && other.values.to_set == values.to_set
63
+ # rubocop:enable Style/CaseEquality
64
64
  end
65
65
 
66
66
  # @api private
@@ -97,8 +97,28 @@ module ModernTreasury
97
97
  # #
98
98
  # # @param value [Symbol, Object]
99
99
  # #
100
+ # # @param state [Hash{Symbol=>Object}] .
101
+ # #
102
+ # # @option state [Boolean] :can_retry
103
+ # #
100
104
  # # @return [Symbol, Object]
101
- # def dump(value) = super
105
+ # def dump(value, state:) = super
106
+
107
+ # @api private
108
+ #
109
+ # @param depth [Integer]
110
+ #
111
+ # @return [String]
112
+ def inspect(depth: 0)
113
+ if depth.positive?
114
+ return is_a?(Module) ? super() : self.class.name
115
+ end
116
+
117
+ members = values.map { ModernTreasury::Internal::Type::Converter.inspect(_1, depth: depth.succ) }
118
+ prefix = is_a?(Module) ? name : self.class.name
119
+
120
+ "#{prefix}[#{members.join(' | ')}]"
121
+ end
102
122
  end
103
123
  end
104
124
  end
@@ -13,6 +13,10 @@ module ModernTreasury
13
13
  class HashOf
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.[](type_info, spec = {}) = new(type_info, spec)
31
+ def self.[](...) = new(...)
28
32
 
29
33
  # @param other [Object]
30
34
  #
@@ -99,12 +103,16 @@ module ModernTreasury
99
103
  #
100
104
  # @param value [Hash{Object=>Object}, Object]
101
105
  #
106
+ # @param state [Hash{Symbol=>Object}] .
107
+ #
108
+ # @option state [Boolean] :can_retry
109
+ #
102
110
  # @return [Hash{Symbol=>Object}, Object]
103
- def dump(value)
111
+ def dump(value, state:)
104
112
  target = item_type
105
113
  if value.is_a?(Hash)
106
114
  value.transform_values do
107
- ModernTreasury::Internal::Type::Converter.dump(target, _1)
115
+ ModernTreasury::Internal::Type::Converter.dump(target, _1, state: state)
108
116
  end
109
117
  else
110
118
  super
@@ -136,7 +144,18 @@ module ModernTreasury
136
144
  # @option spec [Boolean] :"nil?"
137
145
  def initialize(type_info, spec = {})
138
146
  @item_type_fn = ModernTreasury::Internal::Type::Converter.type_info(type_info || spec)
139
- @nilable = spec[:nil?]
147
+ @nilable = spec.fetch(:nil?, false)
148
+ end
149
+
150
+ # @api private
151
+ #
152
+ # @param depth [Integer]
153
+ #
154
+ # @return [String]
155
+ def inspect(depth: 0)
156
+ items = ModernTreasury::Internal::Type::Converter.inspect(item_type, depth: depth.succ)
157
+
158
+ "#{self.class}[#{[items, nilable? ? 'nil' : nil].compact.join(' | ')}]"
140
159
  end
141
160
  end
142
161
  end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ModernTreasury
4
+ module Internal
5
+ module Type
6
+ # @api private
7
+ #
8
+ # @abstract
9
+ #
10
+ # Either `Pathname` or `StringIO`.
11
+ class IOLike
12
+ extend ModernTreasury::Internal::Type::Converter
13
+
14
+ private_class_method :new
15
+
16
+ # @param other [Object]
17
+ #
18
+ # @return [Boolean]
19
+ def self.===(other)
20
+ case other
21
+ in StringIO | Pathname | IO
22
+ true
23
+ else
24
+ false
25
+ end
26
+ end
27
+
28
+ # @param other [Object]
29
+ #
30
+ # @return [Boolean]
31
+ def self.==(other) = other.is_a?(Class) && other <= ModernTreasury::Internal::Type::IOLike
32
+
33
+ class << self
34
+ # @api private
35
+ #
36
+ # @param value [StringIO, String, Object]
37
+ #
38
+ # @param state [Hash{Symbol=>Object}] .
39
+ #
40
+ # @option state [Boolean, :strong] :strictness
41
+ #
42
+ # @option state [Hash{Symbol=>Object}] :exactness
43
+ #
44
+ # @option state [Integer] :branched
45
+ #
46
+ # @return [StringIO, Object]
47
+ def coerce(value, state:)
48
+ exactness = state.fetch(:exactness)
49
+ case value
50
+ in String
51
+ exactness[:yes] += 1
52
+ StringIO.new(value)
53
+ in StringIO
54
+ exactness[:yes] += 1
55
+ value
56
+ else
57
+ exactness[:no] += 1
58
+ value
59
+ end
60
+ end
61
+
62
+ # @!parse
63
+ # # @api private
64
+ # #
65
+ # # @param value [Pathname, StringIO, IO, String, Object]
66
+ # #
67
+ # # @param state [Hash{Symbol=>Object}] .
68
+ # #
69
+ # # @option state [Boolean] :can_retry
70
+ # #
71
+ # # @return [Pathname, StringIO, IO, String, Object]
72
+ # def dump(value, state:) = super
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -26,9 +26,18 @@ module ModernTreasury
26
26
  #
27
27
  # @return [Array(Object, Hash{Symbol=>Object})]
28
28
  def dump_request(params)
29
- case (dumped = dump(params))
29
+ state = {can_retry: true}
30
+ case (dumped = dump(params, state: state))
30
31
  in Hash
31
- [dumped.except(:request_options), dumped[:request_options]]
32
+ options = ModernTreasury::Internal::Util.coerce_hash(dumped[:request_options])
33
+ request_options =
34
+ case [options, state.fetch(:can_retry)]
35
+ in [Hash | nil, false]
36
+ {**options.to_h, max_retries: 0}
37
+ else
38
+ options
39
+ end
40
+ [dumped.except(:request_options), request_options]
32
41
  else
33
42
  [dumped, nil]
34
43
  end
@@ -111,9 +111,7 @@ module ModernTreasury
111
111
  #
112
112
  # @return [Boolean]
113
113
  def ==(other)
114
- # rubocop:disable Layout/LineLength
115
- other.is_a?(Module) && other.singleton_class <= ModernTreasury::Internal::Type::Union && other.derefed_variants == derefed_variants
116
- # rubocop:enable Layout/LineLength
114
+ ModernTreasury::Internal::Type::Union === other && other.derefed_variants == derefed_variants
117
115
  end
118
116
 
119
117
  # @api private
@@ -176,15 +174,25 @@ module ModernTreasury
176
174
  #
177
175
  # @param value [Object]
178
176
  #
177
+ # @param state [Hash{Symbol=>Object}] .
178
+ #
179
+ # @option state [Boolean] :can_retry
180
+ #
179
181
  # @return [Object]
180
- def dump(value)
182
+ def dump(value, state:)
181
183
  if (target = resolve_variant(value))
182
- return ModernTreasury::Internal::Type::Converter.dump(target, value)
184
+ return ModernTreasury::Internal::Type::Converter.dump(target, value, state: state)
183
185
  end
184
186
 
185
187
  known_variants.each do
186
188
  target = _2.call
187
- return ModernTreasury::Internal::Type::Converter.dump(target, value) if target === value
189
+ if target === value
190
+ return ModernTreasury::Internal::Type::Converter.dump(
191
+ target,
192
+ value,
193
+ state: state
194
+ )
195
+ end
188
196
  end
189
197
 
190
198
  super
@@ -192,6 +200,22 @@ module ModernTreasury
192
200
 
193
201
  # rubocop:enable Style/CaseEquality
194
202
  # rubocop:enable Style/HashEachMethods
203
+
204
+ # @api private
205
+ #
206
+ # @param depth [Integer]
207
+ #
208
+ # @return [String]
209
+ def inspect(depth: 0)
210
+ if depth.positive?
211
+ return is_a?(Module) ? super() : self.class.name
212
+ end
213
+
214
+ members = variants.map { ModernTreasury::Internal::Type::Converter.inspect(_1, depth: depth.succ) }
215
+ prefix = is_a?(Module) ? name : self.class.name
216
+
217
+ "#{prefix}[#{members.join(' | ')}]"
218
+ end
195
219
  end
196
220
  end
197
221
  end
@@ -13,6 +13,8 @@ module ModernTreasury
13
13
 
14
14
  # rubocop:disable Lint/UnusedMethodArgument
15
15
 
16
+ private_class_method :new
17
+
16
18
  # @param other [Object]
17
19
  #
18
20
  # @return [Boolean]
@@ -47,8 +49,12 @@ module ModernTreasury
47
49
  # #
48
50
  # # @param value [Object]
49
51
  # #
52
+ # # @param state [Hash{Symbol=>Object}] .
53
+ # #
54
+ # # @option state [Boolean] :can_retry
55
+ # #
50
56
  # # @return [Object]
51
- # def dump(value) = super
57
+ # def dump(value, state:) = super
52
58
  end
53
59
 
54
60
  # rubocop:enable Lint/UnusedMethodArgument
@@ -122,7 +122,7 @@ module ModernTreasury
122
122
  # @return [Hash{Object=>Object}, Object]
123
123
  def coerce_hash(input)
124
124
  case input
125
- in NilClass | Array | Set | Enumerator
125
+ in NilClass | Array | Set | Enumerator | StringIO | IO
126
126
  input
127
127
  else
128
128
  input.respond_to?(:to_h) ? input.to_h : input
@@ -348,10 +348,47 @@ module ModernTreasury
348
348
  end
349
349
  end
350
350
 
351
+ # @api private
352
+ class SerializationAdapter
353
+ # @return [Pathname, IO]
354
+ attr_reader :inner
355
+
356
+ # @param a [Object]
357
+ #
358
+ # @return [String]
359
+ def to_json(*a) = (inner.is_a?(IO) ? inner.read : inner.read(binmode: true)).to_json(*a)
360
+
361
+ # @param a [Object]
362
+ #
363
+ # @return [String]
364
+ def to_yaml(*a) = (inner.is_a?(IO) ? inner.read : inner.read(binmode: true)).to_yaml(*a)
365
+
366
+ # @api private
367
+ #
368
+ # @param inner [Pathname, IO]
369
+ def initialize(inner) = @inner = inner
370
+ end
371
+
351
372
  # @api private
352
373
  #
353
374
  # An adapter that satisfies the IO interface required by `::IO.copy_stream`
354
375
  class ReadIOAdapter
376
+ # @api private
377
+ #
378
+ # @return [Boolean, nil]
379
+ def close? = @closing
380
+
381
+ # @api private
382
+ def close
383
+ case @stream
384
+ in Enumerator
385
+ ModernTreasury::Internal::Util.close_fused!(@stream)
386
+ in IO if close?
387
+ @stream.close
388
+ else
389
+ end
390
+ end
391
+
355
392
  # @api private
356
393
  #
357
394
  # @param max_len [Integer, nil]
@@ -396,13 +433,22 @@ module ModernTreasury
396
433
 
397
434
  # @api private
398
435
  #
399
- # @param stream [String, IO, StringIO, Enumerable<String>]
436
+ # @param src [String, Pathname, StringIO, Enumerable<String>]
400
437
  # @param blk [Proc]
401
438
  #
402
439
  # @yieldparam [String]
403
- def initialize(stream, &blk)
404
- @stream = stream.is_a?(String) ? StringIO.new(stream) : stream
405
- @buf = String.new.b
440
+ def initialize(src, &blk)
441
+ @stream =
442
+ case src
443
+ in String
444
+ StringIO.new(src)
445
+ in Pathname
446
+ @closing = true
447
+ src.open(binmode: true)
448
+ else
449
+ src
450
+ end
451
+ @buf = String.new
406
452
  @blk = blk
407
453
  end
408
454
  end
@@ -414,9 +460,10 @@ module ModernTreasury
414
460
  # @return [Enumerable<String>]
415
461
  def writable_enum(&blk)
416
462
  Enumerator.new do |y|
463
+ buf = String.new
417
464
  y.define_singleton_method(:write) do
418
- self << _1.clone
419
- _1.bytesize
465
+ self << buf.replace(_1)
466
+ buf.bytesize
420
467
  end
421
468
 
422
469
  blk.call(y)
@@ -431,29 +478,39 @@ module ModernTreasury
431
478
  # @param boundary [String]
432
479
  # @param key [Symbol, String]
433
480
  # @param val [Object]
434
- private def write_multipart_chunk(y, boundary:, key:, val:)
481
+ # @param closing [Array<Proc>]
482
+ private def write_multipart_chunk(y, boundary:, key:, val:, closing:)
483
+ val = val.inner if val.is_a?(ModernTreasury::Internal::Util::SerializationAdapter)
484
+
435
485
  y << "--#{boundary}\r\n"
436
486
  y << "Content-Disposition: form-data"
437
487
  unless key.nil?
438
488
  name = ERB::Util.url_encode(key.to_s)
439
489
  y << "; name=\"#{name}\""
440
490
  end
441
- if val.is_a?(IO)
491
+ case val
492
+ in Pathname | IO
442
493
  filename = ERB::Util.url_encode(File.basename(val.to_path))
443
494
  y << "; filename=\"#{filename}\""
495
+ else
444
496
  end
445
497
  y << "\r\n"
446
498
  case val
499
+ in Pathname
500
+ y << "Content-Type: application/octet-stream\r\n\r\n"
501
+ io = val.open(binmode: true)
502
+ closing << io.method(:close)
503
+ IO.copy_stream(io, y)
447
504
  in IO
448
505
  y << "Content-Type: application/octet-stream\r\n\r\n"
449
- IO.copy_stream(val.tap(&:rewind), y)
506
+ IO.copy_stream(val, y)
450
507
  in StringIO
451
508
  y << "Content-Type: application/octet-stream\r\n\r\n"
452
509
  y << val.string
453
510
  in String
454
511
  y << "Content-Type: application/octet-stream\r\n\r\n"
455
512
  y << val.to_s
456
- in true | false | Integer | Float | Symbol
513
+ in _ if primitive?(val)
457
514
  y << "Content-Type: text/plain\r\n\r\n"
458
515
  y << val.to_s
459
516
  else
@@ -471,6 +528,7 @@ module ModernTreasury
471
528
  private def encode_multipart_streaming(body)
472
529
  boundary = SecureRandom.urlsafe_base64(60)
473
530
 
531
+ closing = []
474
532
  strio = writable_enum do |y|
475
533
  case body
476
534
  in Hash
@@ -478,19 +536,20 @@ module ModernTreasury
478
536
  case val
479
537
  in Array if val.all? { primitive?(_1) }
480
538
  val.each do |v|
481
- write_multipart_chunk(y, boundary: boundary, key: key, val: v)
539
+ write_multipart_chunk(y, boundary: boundary, key: key, val: v, closing: closing)
482
540
  end
483
541
  else
484
- write_multipart_chunk(y, boundary: boundary, key: key, val: val)
542
+ write_multipart_chunk(y, boundary: boundary, key: key, val: val, closing: closing)
485
543
  end
486
544
  end
487
545
  else
488
- write_multipart_chunk(y, boundary: boundary, key: nil, val: body)
546
+ write_multipart_chunk(y, boundary: boundary, key: nil, val: body, closing: closing)
489
547
  end
490
548
  y << "--#{boundary}--\r\n"
491
549
  end
492
550
 
493
- [boundary, strio]
551
+ fused_io = fused_enum(strio) { closing.each(&:call) }
552
+ [boundary, fused_io]
494
553
  end
495
554
 
496
555
  # @api private
@@ -501,21 +560,21 @@ module ModernTreasury
501
560
  # @return [Object]
502
561
  def encode_content(headers, body)
503
562
  content_type = headers["content-type"]
563
+ body = body.inner if body.is_a?(ModernTreasury::Internal::Util::SerializationAdapter)
564
+
504
565
  case [content_type, body]
505
- in [%r{^application/(?:vnd\.api\+)?json}, _] unless body.nil?
566
+ in [%r{^application/(?:vnd\.api\+)?json}, Hash | Array | -> { primitive?(_1) }]
506
567
  [headers, JSON.fast_generate(body)]
507
- in [%r{^application/(?:x-)?jsonl}, Enumerable]
568
+ in [%r{^application/(?:x-)?jsonl}, Enumerable] unless body.is_a?(StringIO) || body.is_a?(IO)
508
569
  [headers, body.lazy.map { JSON.fast_generate(_1) }]
509
- in [%r{^multipart/form-data}, Hash | IO | StringIO]
570
+ in [%r{^multipart/form-data}, Hash | Pathname | StringIO | IO]
510
571
  boundary, strio = encode_multipart_streaming(body)
511
572
  headers = {**headers, "content-type" => "#{content_type}; boundary=#{boundary}"}
512
573
  [headers, strio]
513
- in [_, IO]
514
- [headers, body.tap(&:rewind)]
515
- in [_, StringIO]
516
- [headers, body.string]
517
574
  in [_, Symbol | Numeric]
518
575
  [headers, body.to_s]
576
+ in [_, StringIO]
577
+ [headers, body.string]
519
578
  else
520
579
  [headers, body]
521
580
  end
@@ -523,6 +582,27 @@ module ModernTreasury
523
582
 
524
583
  # @api private
525
584
  #
585
+ # https://www.iana.org/assignments/character-sets/character-sets.xhtml
586
+ #
587
+ # @param content_type [String]
588
+ # @param text [String]
589
+ def force_charset!(content_type, text:)
590
+ charset = /charset=([^;\s]+)/.match(content_type)&.captures&.first
591
+
592
+ return unless charset
593
+
594
+ begin
595
+ encoding = Encoding.find(charset)
596
+ text.force_encoding(encoding)
597
+ rescue ArgumentError
598
+ nil
599
+ end
600
+ end
601
+
602
+ # @api private
603
+ #
604
+ # Assumes each chunk in stream has `Encoding::BINARY`.
605
+ #
526
606
  # @param headers [Hash{String=>String}, Net::HTTPHeader]
527
607
  # @param stream [Enumerable<String>]
528
608
  # @param suppress_error [Boolean]
@@ -530,7 +610,7 @@ module ModernTreasury
530
610
  # @raise [JSON::ParserError]
531
611
  # @return [Object]
532
612
  def decode_content(headers, stream:, suppress_error: false)
533
- case headers["content-type"]
613
+ case (content_type = headers["content-type"])
534
614
  in %r{^application/(?:vnd\.api\+)?json}
535
615
  json = stream.to_a.join
536
616
  begin
@@ -547,11 +627,10 @@ module ModernTreasury
547
627
  in %r{^text/event-stream}
548
628
  lines = decode_lines(stream)
549
629
  decode_sse(lines)
550
- in %r{^text/}
551
- stream.to_a.join
552
630
  else
553
- # TODO: parsing other response types
554
- StringIO.new(stream.to_a.join)
631
+ text = stream.to_a.join
632
+ force_charset!(content_type, text: text)
633
+ StringIO.new(text)
555
634
  end
556
635
  end
557
636
  end
@@ -616,12 +695,17 @@ module ModernTreasury
616
695
  class << self
617
696
  # @api private
618
697
  #
698
+ # Assumes Strings have been forced into having `Encoding::BINARY`.
699
+ #
700
+ # This decoder is responsible for reassembling lines split across multiple
701
+ # fragments.
702
+ #
619
703
  # @param enum [Enumerable<String>]
620
704
  #
621
705
  # @return [Enumerable<String>]
622
706
  def decode_lines(enum)
623
707
  re = /(\r\n|\r|\n)/
624
- buffer = String.new.b
708
+ buffer = String.new
625
709
  cr_seen = nil
626
710
 
627
711
  chain_fused(enum) do |y|
@@ -652,6 +736,8 @@ module ModernTreasury
652
736
  #
653
737
  # https://html.spec.whatwg.org/multipage/server-sent-events.html#parsing-an-event-stream
654
738
  #
739
+ # Assumes that `lines` has been decoded with `#decode_lines`.
740
+ #
655
741
  # @param lines [Enumerable<String>]
656
742
  #
657
743
  # @return [Enumerable<Hash{Symbol=>Object}>]
@@ -675,7 +761,7 @@ module ModernTreasury
675
761
  in "event"
676
762
  current.merge!(event: value)
677
763
  in "data"
678
- (current[:data] ||= String.new.b) << (value << "\n")
764
+ (current[:data] ||= String.new) << (value << "\n")
679
765
  in "id" unless value.include?("\0")
680
766
  current.merge!(id: value)
681
767
  in "retry" if /^\d+$/ =~ value
@@ -3,6 +3,10 @@
3
3
  module ModernTreasury
4
4
  # @api private
5
5
  module Internal
6
- OMIT = Object.new.freeze
6
+ OMIT =
7
+ Object.new.tap do
8
+ _1.define_singleton_method(:inspect) { "#<#{ModernTreasury::Internal}::OMIT>" }
9
+ end
10
+ .freeze
7
11
  end
8
12
  end
@@ -21,8 +21,8 @@ module ModernTreasury
21
21
 
22
22
  # @!attribute file
23
23
  #
24
- # @return [IO, StringIO]
25
- required :file, IO
24
+ # @return [Pathname, StringIO]
25
+ required :file, ModernTreasury::Internal::Type::IOLike
26
26
 
27
27
  # @!attribute [r] document_type
28
28
  # A category given to the document, can be `null`.
@@ -37,7 +37,7 @@ module ModernTreasury
37
37
  # @!parse
38
38
  # # @param documentable_id [String]
39
39
  # # @param documentable_type [Symbol, ModernTreasury::Models::DocumentCreateParams::DocumentableType]
40
- # # @param file [IO, StringIO]
40
+ # # @param file [Pathname, StringIO]
41
41
  # # @param document_type [String]
42
42
  # # @param request_options [ModernTreasury::RequestOptions, Hash{Symbol=>Object}]
43
43
  # #
@@ -496,8 +496,8 @@ module ModernTreasury
496
496
 
497
497
  # @!attribute file
498
498
  #
499
- # @return [IO, StringIO]
500
- required :file, IO
499
+ # @return [Pathname, StringIO]
500
+ required :file, ModernTreasury::Internal::Type::IOLike
501
501
 
502
502
  # @!attribute [r] document_type
503
503
  # A category given to the document, can be `null`.
@@ -512,7 +512,7 @@ module ModernTreasury
512
512
  # @!parse
513
513
  # # @param documentable_id [String]
514
514
  # # @param documentable_type [Symbol, ModernTreasury::Models::PaymentOrderCreateParams::Document::DocumentableType]
515
- # # @param file [IO, StringIO]
515
+ # # @param file [Pathname, StringIO]
516
516
  # # @param document_type [String]
517
517
  # #
518
518
  # def initialize(documentable_id:, documentable_type:, file:, document_type: nil, **) = super
@@ -9,7 +9,7 @@ module ModernTreasury
9
9
  #
10
10
  # @param documentable_id [String]
11
11
  # @param documentable_type [Symbol, ModernTreasury::Models::DocumentCreateParams::DocumentableType]
12
- # @param file [IO, StringIO]
12
+ # @param file [Pathname, StringIO]
13
13
  # @param document_type [String]
14
14
  # @param request_options [ModernTreasury::RequestOptions, Hash{Symbol=>Object}, nil]
15
15
  #
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ModernTreasury
4
- VERSION = "0.1.0.pre.alpha.17"
4
+ VERSION = "0.1.0.pre.alpha.18"
5
5
  end
@@ -40,6 +40,7 @@ require_relative "modern_treasury/internal/util"
40
40
  require_relative "modern_treasury/internal/type/converter"
41
41
  require_relative "modern_treasury/internal/type/unknown"
42
42
  require_relative "modern_treasury/internal/type/boolean"
43
+ require_relative "modern_treasury/internal/type/io_like"
43
44
  require_relative "modern_treasury/internal/type/enum"
44
45
  require_relative "modern_treasury/internal/type/union"
45
46
  require_relative "modern_treasury/internal/type/array_of"
@@ -160,8 +160,9 @@ module ModernTreasury
160
160
  api_key: ENV["MODERN_TREASURY_API_KEY"],
161
161
  # Defaults to `ENV["MODERN_TREASURY_ORGANIZATION_ID"]`
162
162
  organization_id: ENV["MODERN_TREASURY_ORGANIZATION_ID"],
163
- # Override the default base URL for the API, e.g., `"https://api.example.com/v2/"`
164
- base_url: nil,
163
+ # Override the default base URL for the API, e.g.,
164
+ # `"https://api.example.com/v2/"`. Defaults to `ENV["MODERN_TREASURY_BASE_URL"]`
165
+ base_url: ENV["MODERN_TREASURY_BASE_URL"],
165
166
  # Max number of retries to attempt after a failed retryable request.
166
167
  max_retries: DEFAULT_MAX_RETRIES,
167
168
  timeout: DEFAULT_TIMEOUT_IN_SECONDS,
@@ -22,6 +22,7 @@ module ModernTreasury
22
22
  sig { override.params(blk: T.proc.params(arg0: Elem).void).void }
23
23
  def auto_paging_each(&blk); end
24
24
 
25
+ # @api private
25
26
  sig { returns(String) }
26
27
  def inspect; end
27
28
  end