Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.1.0-alpha.4"
".": "0.1.0-alpha.5"
}
3 changes: 3 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,9 @@ Style/MethodCallWithArgsParentheses:
Exclude:
- "**/*.gemspec"

Style/MultilineBlockChain:
Enabled: false

# Perfectly fine.
Style/MultipleComparison:
Enabled: false
Expand Down
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
# Changelog

## 0.1.0-alpha.5 (2025-04-05)

Full Changelog: [v0.1.0-alpha.4...v0.1.0-alpha.5](https://github.com/Increase/increase-ruby/compare/v0.1.0-alpha.4...v0.1.0-alpha.5)

### Features

* allow all valid `JSON` types to be encoded ([#26](https://github.com/Increase/increase-ruby/issues/26)) ([92760b3](https://github.com/Increase/increase-ruby/commit/92760b3aba92abca8c6b4d6550d75b94c1a8fbc2))
* support query, header, and body params that have identical names ([#25](https://github.com/Increase/increase-ruby/issues/25)) ([def73dd](https://github.com/Increase/increase-ruby/commit/def73dd349fa2aec3074e16bdfa2a165bf4fc1e1))


### Bug Fixes

* converter should transform stringio into string where applicable ([#28](https://github.com/Increase/increase-ruby/issues/28)) ([68e4e9d](https://github.com/Increase/increase-ruby/commit/68e4e9df4a5938442eb890da6f1918f04d34e333))


### Chores

* document LSP support in read me ([#24](https://github.com/Increase/increase-ruby/issues/24)) ([778538d](https://github.com/Increase/increase-ruby/commit/778538da18c49156d45c68c9370c3628fd7e594a))
* **internal:** version bump ([#19](https://github.com/Increase/increase-ruby/issues/19)) ([fd9e8ad](https://github.com/Increase/increase-ruby/commit/fd9e8ada315a49377dbb2aa8ec6af48a180fb651))
* misc sdk polish ([#23](https://github.com/Increase/increase-ruby/issues/23)) ([e056d8a](https://github.com/Increase/increase-ruby/commit/e056d8a96d3da4568daf30d68f980a81c69ab5dc))
* rename confusing `Type::BooleanModel` to `Type::Boolean` ([#27](https://github.com/Increase/increase-ruby/issues/27)) ([ae0a5ee](https://github.com/Increase/increase-ruby/commit/ae0a5ee0e1c0177ab6aa08032f29655b5412b37d))
* simplify internal utils ([#22](https://github.com/Increase/increase-ruby/issues/22)) ([da6ec29](https://github.com/Increase/increase-ruby/commit/da6ec29d5dd5ad6bfea0f3461221f3a80259738d))

## 0.1.0-alpha.4 (2025-04-04)

Full Changelog: [v0.1.0-alpha.3...v0.1.0-alpha.4](https://github.com/Increase/increase-ruby/compare/v0.1.0-alpha.3...v0.1.0-alpha.4)
Expand Down
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ GIT
PATH
remote: .
specs:
increase (0.1.0.pre.alpha.4)
increase (0.1.0.pre.alpha.5)
connection_pool

GEM
Expand Down
30 changes: 25 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ To use this gem, install via Bundler by adding the following to your application
<!-- x-release-please-start-version -->

```ruby
gem "increase", "~> 0.1.0.pre.alpha.3"
gem "increase", "~> 0.1.0.pre.alpha.4"
```

<!-- x-release-please-end -->
Expand Down Expand Up @@ -140,9 +140,23 @@ increase.accounts.create(

## LSP Support

### Sorbet
### Solargraph

This library includes [Solargraph](https://solargraph.org) support for both auto completion and go to definition.

```ruby
gem "solargraph", group: :development
```

After Solargraph is installed, **you must populate its index** either via the provided editor command, or by running the following in your terminal:

```sh
bundle exec solargraph gems
```

**This library emits an intentional warning under the [`tapioca` toolchain](https://github.com/Shopify/tapioca)**. This is normal, and does not impact functionality.
Otherwise Solargraph will not be able to provide type information or auto-completion for any non-indexed libraries.

### Sorbet

This library is written with [Sorbet type definitions](https://sorbet.org/docs/rbi). However, there is no runtime dependency on the `sorbet-runtime`.

Expand All @@ -153,15 +167,21 @@ Due to limitations with the Sorbet type system, where a method otherwise can tak
Please follow Sorbet's [setup guides](https://sorbet.org/docs/adopting) for best experience.

```ruby
model = Increase::Models::AccountCreateParams.new(
params = Increase::Models::AccountCreateParams.new(
name: "New Account!",
entity_id: "entity_n8y8tnk2p9339ti393yi",
program_id: "program_i2v2os4mwza1oetokh9i"
)

increase.accounts.create(**model)
increase.accounts.create(**params)
```

Note: **This library emits an intentional warning under the [`tapioca` toolchain](https://github.com/Shopify/tapioca)**. This is normal, and does not impact functionality.

### Ruby LSP

The Ruby LSP has [best effort support](https://shopify.github.io/ruby-lsp/#guessed-types) for inferring type information from Ruby code, and as such it may not always be able to provide accurate type information.

## Advanced

### Making custom/undocumented requests
Expand Down
2 changes: 1 addition & 1 deletion lib/increase.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
require_relative "increase/internal/util"
require_relative "increase/internal/type/converter"
require_relative "increase/internal/type/unknown"
require_relative "increase/internal/type/boolean_model"
require_relative "increase/internal/type/boolean"
require_relative "increase/internal/type/enum"
require_relative "increase/internal/type/union"
require_relative "increase/internal/type/array_of"
Expand Down
18 changes: 12 additions & 6 deletions lib/increase/internal/type/base_model.rb
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,9 @@ def optional(name_sym, type_info, spec = {})
# @param other [Object]
#
# @return [Boolean]
def ==(other) = other.is_a?(Class) && other <= Increase::Internal::Type::BaseModel && other.fields == fields
def ==(other)
other.is_a?(Class) && other <= Increase::Internal::Type::BaseModel && other.fields == fields
end
end

# @param other [Object]
Expand Down Expand Up @@ -263,6 +265,7 @@ def dump(value)
return super
end

is_param = singleton_class <= Increase::Internal::Type::RequestParameters::Converter
acc = {}

coerced.each do |key, val|
Expand All @@ -271,19 +274,21 @@ def dump(value)
in nil
acc.store(name, super(val))
else
mode, api_name, type_fn = field.fetch_values(:mode, :api_name, :type_fn)
mode, type_fn = field.fetch_values(:mode, :type_fn)
case mode
in :coerce
next
else
target = type_fn.call
api_name = is_param ? name : field.fetch(:api_name)
acc.store(api_name, Increase::Internal::Type::Converter.dump(target, val))
end
end
end

known_fields.each_value do |field|
mode, api_name, const = field.fetch_values(:mode, :api_name, :const)
known_fields.each do |name, field|
mode, const = field.fetch_values(:mode, :const)
api_name = is_param ? name : field.fetch(:api_name)
next if mode == :coerce || acc.key?(api_name) || const == Increase::Internal::OMIT
acc.store(api_name, const)
end
Expand Down Expand Up @@ -357,15 +362,16 @@ def initialize(data = {})
in Hash => coerced
@data = coerced
else
raise ArgumentError.new("Expected a #{Hash} or #{Increase::Internal::Type::BaseModel}, got #{data.inspect}")
message = "Expected a #{Hash} or #{Increase::Internal::Type::BaseModel}, got #{data.inspect}"
raise ArgumentError.new(message)
end
end

# @return [String]
def inspect
rows = self.class.known_fields.keys.map do
"#{_1}=#{@data.key?(_1) ? public_send(_1) : ''}"
rescue Increase::ConversionError
rescue Increase::Errors::ConversionError
"#{_1}=#{@data.fetch(_1)}"
end
"#<#{self.class.name}:0x#{object_id.to_s(16)} #{rows.join(' ')}>"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module Type
# @abstract
#
# Ruby has no Boolean class; this is something for models to refer to.
class BooleanModel
class Boolean
extend Increase::Internal::Type::Converter

# @param other [Object]
Expand All @@ -19,7 +19,7 @@ def self.===(other) = other == true || other == false
# @param other [Object]
#
# @return [Boolean]
def self.==(other) = other.is_a?(Class) && other <= Increase::Internal::Type::BooleanModel
def self.==(other) = other.is_a?(Class) && other <= Increase::Internal::Type::Boolean

class << self
# @api private
Expand Down
7 changes: 6 additions & 1 deletion lib/increase/internal/type/converter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def type_info(spec)
in Hash
type_info(spec.slice(:const, :enum, :union).first&.last)
in true | false
-> { Increase::Internal::Type::BooleanModel }
-> { Increase::Internal::Type::Boolean }
in Increase::Internal::Type::Converter | Class | Symbol
-> { spec }
in NilClass | Integer | Float
Expand Down Expand Up @@ -168,6 +168,9 @@ def coerce(
in String | Symbol | Numeric
exactness[value.is_a?(Numeric) ? :maybe : :yes] += 1
return value.to_s
in StringIO
exactness[:yes] += 1
return value.string
else
if strictness == :strong
message = "no implicit conversion of #{value.class} into #{target.inspect}"
Expand Down Expand Up @@ -209,7 +212,9 @@ def coerce(
#
# @return [Object]
def dump(target, value)
# rubocop:disable Layout/LineLength
target.is_a?(Increase::Internal::Type::Converter) ? target.dump(value) : Increase::Internal::Type::Unknown.dump(value)
# rubocop:enable Layout/LineLength
end
end
end
Expand Down
2 changes: 2 additions & 0 deletions lib/increase/internal/type/enum.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ def ===(other) = values.include?(other)
#
# @return [Boolean]
def ==(other)
# rubocop:disable Layout/LineLength
other.is_a?(Module) && other.singleton_class <= Increase::Internal::Type::Enum && other.values.to_set == values.to_set
# rubocop:enable Layout/LineLength
end

# @api private
Expand Down
49 changes: 16 additions & 33 deletions lib/increase/internal/util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class << self
# @return [Boolean]
def primitive?(input)
case input
in true | false | Integer | Float | Symbol | String
in true | false | Numeric | Symbol | String
true
else
false
Expand All @@ -70,13 +70,11 @@ def primitive?(input)

# @api private
#
# @param input [Object]
# @param input [String, Boolean]
#
# @return [Boolean, Object]
def coerce_boolean(input)
case input.is_a?(String) ? input.downcase : input
in Numeric
input.nonzero?
in "true"
true
in "false"
Expand All @@ -88,7 +86,7 @@ def coerce_boolean(input)

# @api private
#
# @param input [Object]
# @param input [String, Boolean]
#
# @raise [ArgumentError]
# @return [Boolean, nil]
Expand All @@ -103,34 +101,20 @@ def coerce_boolean!(input)

# @api private
#
# @param input [Object]
# @param input [String, Integer]
#
# @return [Integer, Object]
def coerce_integer(input)
case input
in true
1
in false
0
else
Integer(input, exception: false) || input
end
Integer(input, exception: false) || input
end

# @api private
#
# @param input [Object]
# @param input [String, Integer, Float]
#
# @return [Float, Object]
def coerce_float(input)
case input
in true
1.0
in false
0.0
else
Float(input, exception: false) || input
end
Float(input, exception: false) || input
end

# @api private
Expand Down Expand Up @@ -159,12 +143,7 @@ class << self
private def deep_merge_lr(lhs, rhs, concat: false)
case [lhs, rhs, concat]
in [Hash, Hash, _]
rhs_cleaned = rhs.reject { _2 == Increase::Internal::OMIT }
lhs
.reject { |key, _| rhs[key] == Increase::Internal::OMIT }
.merge(rhs_cleaned) do |_, old_val, new_val|
deep_merge_lr(old_val, new_val, concat: concat)
end
lhs.merge(rhs) { deep_merge_lr(_2, _3, concat: concat) }
in [Array, Array, true]
lhs.concat(rhs)
else
Expand Down Expand Up @@ -362,7 +341,7 @@ def normalized_headers(*headers)
value =
case val
in Array
val.map { _1.to_s.strip }.join(", ")
val.filter_map { _1&.to_s&.strip }.join(", ")
else
val&.to_s&.strip
end
Expand Down Expand Up @@ -469,7 +448,7 @@ class << self
case val
in IO
y << "Content-Type: application/octet-stream\r\n\r\n"
IO.copy_stream(val, y)
IO.copy_stream(val.tap(&:rewind), y)
in StringIO
y << "Content-Type: application/octet-stream\r\n\r\n"
y << val.string
Expand Down Expand Up @@ -525,16 +504,20 @@ class << self
def encode_content(headers, body)
content_type = headers["content-type"]
case [content_type, body]
in [%r{^application/(?:vnd\.api\+)?json}, Hash | Array]
in [%r{^application/(?:vnd\.api\+)?json}, _] unless body.nil?
[headers, JSON.fast_generate(body)]
in [%r{^application/(?:x-)?jsonl}, Enumerable]
[headers, body.lazy.map { JSON.fast_generate(_1) }]
in [%r{^multipart/form-data}, Hash | IO | StringIO]
boundary, strio = encode_multipart_streaming(body)
headers = {**headers, "content-type" => "#{content_type}; boundary=#{boundary}"}
[headers, strio]
in [_, IO]
[headers, body.tap(&:rewind)]
in [_, StringIO]
[headers, body.string]
in [_, Symbol | Numeric]
[headers, body.to_s]
else
[headers, body]
end
Expand Down Expand Up @@ -673,7 +656,7 @@ def decode_lines(enum)
#
# @param lines [Enumerable<String>]
#
# @return [Hash{Symbol=>Object}]
# @return [Enumerable<Hash{Symbol=>Object}>]
def decode_sse(lines)
# rubocop:disable Metrics/BlockLength
chain_fused(lines) do |y|
Expand Down
2 changes: 1 addition & 1 deletion lib/increase/models/account_transfer_create_params.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class AccountTransferCreateParams < Increase::Internal::Type::BaseModel
# Whether the transfer requires explicit approval via the dashboard or API.
#
# @return [Boolean, nil]
optional :require_approval, Increase::Internal::Type::BooleanModel
optional :require_approval, Increase::Internal::Type::Boolean

# @!parse
# # @return [Boolean]
Expand Down
2 changes: 1 addition & 1 deletion lib/increase/models/ach_transfer_create_params.rb
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ class ACHTransferCreateParams < Increase::Internal::Type::BaseModel
# Whether the transfer requires explicit approval via the dashboard or API.
#
# @return [Boolean, nil]
optional :require_approval, Increase::Internal::Type::BooleanModel
optional :require_approval, Increase::Internal::Type::Boolean

# @!parse
# # @return [Boolean]
Expand Down
Loading
Loading