treezor_connect 0.21.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f42fbc240623d62e13b086515e5e3d0bd709f9b8f3b8700a10fbd213db2cce6a
4
- data.tar.gz: 85e14d31652d27fe8189921dc6220d2974ed4761e54fcaecce8531797cfd412c
3
+ metadata.gz: 9853144e2f1a2e86103752fae6340f674ecd3f4c25e38f32cad3f326a0021c63
4
+ data.tar.gz: 932fd89d512e1eeb940ef10870a5938843e3c9129c9b6f2c0bfa0387dbbe20f6
5
5
  SHA512:
6
- metadata.gz: cc3ee88a1189859357ec0b782bcabef1e47efb37dafeb0c759d48bc509de883facecd0e3dbe8404a432ecd0bed614a80fff72561fb11e9568fb19540b04de762
7
- data.tar.gz: 4448aa73525211e191755873caf1ac1cac04f695a33d925855c654e193f9e4cf433c9c451362c97ff57c098f18306b9118bd8d97c2449f6184141b748b6ddc2b
6
+ metadata.gz: 208436fb13bdd61369741a1ce577a6dc798c47ab48467676b2cdb9e80c04bf9e859054e00fbd3f0436a9ed8b88b2c2ccdc8a488bc9baf30f7f04a88749f3f2de
7
+ data.tar.gz: d630695ec6682459dacaf7bdb67c13699f1ba039248d173433a3908637984356c246e5db0c74db6c848a1cc5d6908df4e0dbed0e6dc6e0b0cf8193f8892a726e
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TreezorConnect
4
+ module ApiOperations
5
+ module BulkCreate
6
+ def bulk_create(params_list, access_token = nil)
7
+ params_list = params_list.map { |params| { body: params } }
8
+ treezor_responses = parallel_request(:post, resource_url, params_list:, access_token:)
9
+ treezor_responses.map do |treezor_response|
10
+ if treezor_response.is_a?(ApiError)
11
+ treezor_response
12
+ else
13
+ data = extract_response_data(treezor_response, extract_all_objects: false)
14
+ Util.convert_to_treezor_object(data, { object_class: self::OBJECT_NAME })
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -3,15 +3,10 @@
3
3
  module TreezorConnect
4
4
  module ApiOperations
5
5
  module Create
6
+ include CreateOperation
7
+
6
8
  def create(params = {}, access_token = nil)
7
- treezor_response = request(:post, resource_url, params: { body: params }, access_token:)
8
- data = extract_response_data(treezor_response, extract_all_objects: false)
9
- Util.convert_to_treezor_object(data, { object_class: self::OBJECT_NAME })
10
- rescue AlreadyCreatedError => e
11
- data = extract_response_data(e.treezor_response, extract_all_objects: false)
12
- e.treezor_response = nil
13
- e.object = Util.convert_to_treezor_object(data, { object_class: self::OBJECT_NAME })
14
- raise
9
+ perform_create(resource_url, params, access_token)
15
10
  end
16
11
  end
17
12
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TreezorConnect
4
+ module ApiOperations
5
+ module CreateOperation
6
+ def perform_create(url, params, access_token)
7
+ response = request(:post, url, params: { body: params }, access_token:)
8
+ build_object_from_response(response)
9
+ rescue AlreadyCreatedError => e
10
+ e.object = build_object_from_response(e.treezor_response)
11
+ e.treezor_response = nil
12
+ raise
13
+ end
14
+
15
+ def build_object_from_response(response)
16
+ data = extract_response_data(response, extract_all_objects: false)
17
+ Util.convert_to_treezor_object(data, { object_class: self::OBJECT_NAME })
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TreezorConnect
4
+ module ApiOperations
5
+ module NestedCreate
6
+ include CreateOperation
7
+
8
+ def create(parent_id, params = {}, access_token = nil)
9
+ perform_create(resource_url(parent_id), params, access_token)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TreezorConnect
4
+ module ApiOperations
5
+ module NestedDelete
6
+ def delete(parent_id, id, access_token = nil)
7
+ url = [resource_url(parent_id), id].join('/')
8
+ treezor_response = request(:delete, url, access_token:)
9
+ data = extract_response_data(treezor_response, extract_all_objects: false)
10
+ Util.convert_to_treezor_object(data, { object_class: self::OBJECT_NAME })
11
+ end
12
+ end
13
+ end
14
+ end
@@ -7,14 +7,19 @@ module TreezorConnect
7
7
  def request(method, url, params: {}, headers: {}, access_token: nil)
8
8
  params = Util.normalize_params(params)
9
9
  client = TreezorConnect::Client.new(access_token)
10
- response = client.execute_request(
11
- method, url,
12
- headers:,
13
- params:
14
- )
10
+ response = client.execute_request(method, url, headers:, params:)
15
11
  TreezorResponse.from_http_response(response)
16
12
  end
17
13
 
14
+ def parallel_request(method, url, params_list: {}, headers: {}, access_token: nil)
15
+ params_list = params_list.map { |params| Util.normalize_params(params) }
16
+ client = TreezorConnect::Client.new(access_token)
17
+ responses = client.execute_parallel_requests(method, url, headers:, params_list:)
18
+ responses.map do |response|
19
+ response.is_a?(ApiError) ? response : TreezorResponse.from_http_response(response)
20
+ end
21
+ end
22
+
18
23
  def extract_response_data(response, extract_all_objects: true)
19
24
  if defined?(self::OBJECT_KEY) && response.data.key?(self::OBJECT_KEY)
20
25
  objects = response.data.fetch(self::OBJECT_KEY)
@@ -5,31 +5,46 @@ module TreezorConnect
5
5
  attr_reader :access_token
6
6
 
7
7
  def initialize(access_token)
8
- @access_token = access_token.nil? ? default_access_token : access_token
8
+ @access_token = access_token || default_access_token
9
9
  @conn = Faraday.new(
10
10
  url: TreezorConnect.api_base_url,
11
- headers: { 'Authorization' => "Bearer #{@access_token}" }
12
- ) do |f|
13
- f.response :logger, Logger.new($stdout) if ENV['ENABLE_HTTP_LOGGING']
14
- f.adapter Faraday.default_adapter
11
+ headers: { 'Authorization' => "Bearer #{@access_token}" },
12
+ parallel_manager:
13
+ ) do |faraday|
14
+ faraday.response :logger, Logger.new($stdout) if ENV['ENABLE_HTTP_LOGGING']
15
+ faraday.adapter :typhoeus
15
16
  end
16
17
  end
17
18
 
18
19
  def execute_request(method, path, headers: {}, params: {})
19
20
  response = conn.public_send(method, path) do |req|
20
21
  req.headers.merge!(headers)
21
- req.params.merge!(params[:query]) if params[:query]
22
- apply_body(req, params)
22
+ configure_request(req, params)
23
23
  end
24
24
 
25
25
  process_response(response)
26
26
  end
27
27
 
28
+ def execute_parallel_requests(method, path, headers: {}, params_list: [])
29
+ responses = []
30
+ conn.in_parallel do
31
+ params_list.each do |params|
32
+ responses << conn.public_send(method, path) do |req|
33
+ req.headers.merge!(headers)
34
+ configure_request(req, params)
35
+ end
36
+ end
37
+ end
38
+
39
+ responses.map { |response| process_parallel_response(response) }
40
+ end
41
+
28
42
  private
29
43
 
30
44
  attr_reader :conn
31
45
 
32
- def apply_body(req, params)
46
+ def configure_request(req, params)
47
+ req.params.merge!(params[:query]) if params[:query]
33
48
  if params[:form]
34
49
  req.headers['Content-Type'] = 'application/x-www-form-urlencoded'
35
50
  req.body = URI.encode_www_form(params[:form])
@@ -47,6 +62,14 @@ module TreezorConnect
47
62
  )
48
63
  end
49
64
 
65
+ def parallel_manager
66
+ @parallel_manager ||= begin
67
+ # Currently library default is 200 but this way we are future-proof
68
+ max_concurrency = TreezorConnect.max_concurrency || Typhoeus::Hydra.new.max_concurrency
69
+ Typhoeus::Hydra.new(max_concurrency:)
70
+ end
71
+ end
72
+
50
73
  def fetch_access_token
51
74
  oauth_client.client_credentials.get_token.token
52
75
  end
@@ -57,12 +80,22 @@ module TreezorConnect
57
80
  elsif response.status == 303
58
81
  raise AlreadyCreatedError, response
59
82
  else
60
- raise_api_error(http_status: response.status, http_body: JSON.parse(response.body))
83
+ raise build_api_error(http_status: response.status, http_body: JSON.parse(response.body))
61
84
  end
62
85
  end
63
86
 
64
- def raise_api_error(http_status:, http_body:)
65
- raise ApiError.new(
87
+ def process_parallel_response(response)
88
+ if response.success?
89
+ response
90
+ elsif response.status == 303
91
+ AlreadyCreatedError.new(response)
92
+ else
93
+ build_api_error(http_status: response.status, http_body: JSON.parse(response.body))
94
+ end
95
+ end
96
+
97
+ def build_api_error(http_status:, http_body:)
98
+ ApiError.new(
66
99
  "API request failed: #{http_body.inspect} (HTTP response code was #{http_status})",
67
100
  http_body,
68
101
  http_status
@@ -74,19 +107,20 @@ module TreezorConnect
74
107
 
75
108
  decoded_token = JWT.decode(current_access_token, nil, false).first
76
109
  decoded_token['exp'] < Time.now.to_i
110
+ rescue JWT::DecodeError
111
+ true
77
112
  end
78
113
 
79
114
  def default_access_token
80
- if current_access_token_expired?
81
- access_token = fetch_access_token
82
- Thread.current[:treezor_default_access_token] = access_token if ENV['SKIP_ACCESS_TOKEN_IN_THREAD'].nil?
83
- else
84
- current_access_token
85
- end
115
+ return current_access_token unless current_access_token_expired?
116
+
117
+ token = fetch_access_token
118
+ Thread.current[:treezor_default_access_token] = token if ENV['SKIP_ACCESS_TOKEN_IN_THREAD'].nil?
119
+ token
86
120
  end
87
121
 
88
122
  def current_access_token
89
- @current_access_token ||= Thread.current[:treezor_default_access_token]
123
+ Thread.current[:treezor_default_access_token]
90
124
  end
91
125
  end
92
126
  end
@@ -11,6 +11,7 @@ module TreezorConnect
11
11
  end
12
12
 
13
13
  extend TreezorConnect::ApiOperations::Create
14
+ extend TreezorConnect::ApiOperations::BulkCreate
14
15
  extend TreezorConnect::ApiOperations::Fetch
15
16
  end
16
17
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TreezorConnect
4
+ class User
5
+ class Relationship < ApiResource
6
+ extend TreezorConnect::ApiOperations::NestedCreate
7
+ extend TreezorConnect::ApiOperations::NestedDelete
8
+
9
+ OBJECT_NAME = 'user/relationship'
10
+ OBJECT_PRIMARY_KEY = 'relationshipId'
11
+
12
+ def self.resource_url(user_id)
13
+ "/v1/users/#{user_id}/relationships"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -10,6 +10,7 @@ require 'treezor_connect/resources/payin'
10
10
  require 'treezor_connect/resources/payout'
11
11
  require 'treezor_connect/resources/tax_residence'
12
12
  require 'treezor_connect/resources/user'
13
+ require 'treezor_connect/resources/user/relationship'
13
14
  require 'treezor_connect/resources/oauth/token'
14
15
  require 'treezor_connect/resources/sca/external_operation'
15
16
  require 'treezor_connect/resources/sca/passcode'
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'faraday'
4
+ require 'faraday/typhoeus'
4
5
  require 'oauth2'
5
6
  require 'logger'
6
7
 
@@ -18,10 +19,14 @@ require 'treezor_connect/errors'
18
19
  # API operations
19
20
  require 'treezor_connect/api_operations/fetch'
20
21
  require 'treezor_connect/api_operations/list'
22
+ require 'treezor_connect/api_operations/create_operation'
21
23
  require 'treezor_connect/api_operations/create'
24
+ require 'treezor_connect/api_operations/nested_create'
25
+ require 'treezor_connect/api_operations/bulk_create'
22
26
  require 'treezor_connect/api_operations/request'
23
27
  require 'treezor_connect/api_operations/update'
24
28
  require 'treezor_connect/api_operations/delete'
29
+ require 'treezor_connect/api_operations/nested_delete'
25
30
 
26
31
  # API resources
27
32
  require 'treezor_connect/api_resource'
@@ -29,7 +34,7 @@ require 'treezor_connect/resources'
29
34
 
30
35
  module TreezorConnect
31
36
  class << self
32
- attr_accessor :api_base_url, :client_id, :client_secret
37
+ attr_accessor :api_base_url, :client_id, :client_secret, :max_concurrency
33
38
  end
34
39
 
35
40
  def self.configure
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: treezor_connect
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.21.0
4
+ version: 0.23.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - stefakins
8
8
  - jbauzone
9
+ autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2026-06-08 00:00:00.000000000 Z
12
+ date: 2026-06-16 00:00:00.000000000 Z
12
13
  dependencies: []
13
14
  description: A gem for making HTTP calls to Treezor Connect.
14
15
  email: stefan.atkinson69@gmail.com
@@ -17,10 +18,14 @@ extensions: []
17
18
  extra_rdoc_files: []
18
19
  files:
19
20
  - lib/treezor_connect.rb
21
+ - lib/treezor_connect/api_operations/bulk_create.rb
20
22
  - lib/treezor_connect/api_operations/create.rb
23
+ - lib/treezor_connect/api_operations/create_operation.rb
21
24
  - lib/treezor_connect/api_operations/delete.rb
22
25
  - lib/treezor_connect/api_operations/fetch.rb
23
26
  - lib/treezor_connect/api_operations/list.rb
27
+ - lib/treezor_connect/api_operations/nested_create.rb
28
+ - lib/treezor_connect/api_operations/nested_delete.rb
24
29
  - lib/treezor_connect/api_operations/request.rb
25
30
  - lib/treezor_connect/api_operations/update.rb
26
31
  - lib/treezor_connect/api_resource.rb
@@ -43,6 +48,7 @@ files:
43
48
  - lib/treezor_connect/resources/sct_inst/recall.rb
44
49
  - lib/treezor_connect/resources/tax_residence.rb
45
50
  - lib/treezor_connect/resources/user.rb
51
+ - lib/treezor_connect/resources/user/relationship.rb
46
52
  - lib/treezor_connect/treezor_object.rb
47
53
  - lib/treezor_connect/treezor_response.rb
48
54
  - lib/treezor_connect/util.rb
@@ -51,6 +57,7 @@ licenses:
51
57
  - MIT
52
58
  metadata:
53
59
  rubygems_mfa_required: 'true'
60
+ post_install_message:
54
61
  rdoc_options: []
55
62
  require_paths:
56
63
  - lib
@@ -65,7 +72,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
65
72
  - !ruby/object:Gem::Version
66
73
  version: '0'
67
74
  requirements: []
68
- rubygems_version: 3.6.5
75
+ rubygems_version: 3.4.19
76
+ signing_key:
69
77
  specification_version: 4
70
78
  summary: A gem for making HTTP calls to Treezor Connect.
71
79
  test_files: []