folio_client 0.11.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5e7b3edaad66a7bca966c6316eb979f722fe0eb2336def7f45eda9952a2a5ee
4
- data.tar.gz: 7d4d555e56d607acbb4649ef59e94e5ab417ee1f4f78fce2a999864f9e8486ee
3
+ metadata.gz: 7918be772bc1758840166cbb6f0fb66bfbf4765f636118d971efef2192a947df
4
+ data.tar.gz: 86d3c7e5656e849cf3358ddf7e22463bd65527cedf017a9a31dfdd2606bad88a
5
5
  SHA512:
6
- metadata.gz: ad63a3b363409b8561ca3ecf0f94b05f915ffe8ec621915e692f7d805d1f1c140b7626d2c95d613cc35974c08425a313e33ac72cc3249f68a1b3aece8d182688
7
- data.tar.gz: 6e0bfb061e5fafda66cc4690726bb69a17e3ccdd474997bb433d3fa9f02d55f2e6c103edc263ab82e22d69c36960576a7acc5ab73f23b7e6364acee487efb99e
6
+ metadata.gz: 9471247fec95c9df775cd359896c788d124173477b74f1124d41641f76e6d61438fe7b5e7c10fb3ee7d6efb9f5dba11c9b0b7b45fb9040520f6668cba626fc1d
7
+ data.tar.gz: 4f0adf00bb277b709a68552e7f2b5119e7b8597723ffc3c4f500d850e2c8470df0249a19e35a98bcfcf2ef6daa3befb8155e57d5f69c8d825fe3b1806cd240a5
File without changes
data/.rubocop/custom.yml CHANGED
@@ -34,9 +34,9 @@ RSpec/SubjectDeclaration: # new in 2.5
34
34
  Enabled: true
35
35
  RSpec/VerifiedDoubleReference: # new in 2.10.0
36
36
  Enabled: true
37
- RSpec/FactoryBot/ConsistentParenthesesStyle: # new in 2.14
37
+ FactoryBot/ConsistentParenthesesStyle: # new in 2.14
38
38
  Enabled: true
39
- RSpec/FactoryBot/SyntaxMethods: # new in 2.7
39
+ FactoryBot/SyntaxMethods: # new in 2.7
40
40
  Enabled: true
41
41
  RSpec/Rails/AvoidSetupHook: # new in 2.4
42
42
  Enabled: true
@@ -58,7 +58,7 @@ RSpec/DuplicatedMetadata: # new in 2.16
58
58
  Enabled: true
59
59
  RSpec/PendingWithoutReason: # new in 2.16
60
60
  Enabled: true
61
- RSpec/FactoryBot/FactoryNameStyle: # new in 2.16
61
+ FactoryBot/FactoryNameStyle: # new in 2.16
62
62
  Enabled: true
63
63
  RSpec/Rails/MinitestAssertions: # new in 2.17
64
64
  Enabled: true
@@ -68,3 +68,17 @@ RSpec/SkipBlockInsideExample: # new in 2.19
68
68
  Enabled: true
69
69
  RSpec/Rails/TravelAround: # new in 2.19
70
70
  Enabled: true
71
+ FactoryBot/AssociationStyle: # new in 2.23
72
+ Enabled: true
73
+ FactoryBot/FactoryAssociationWithStrategy: # new in 2.23
74
+ Enabled: true
75
+ FactoryBot/RedundantFactoryOption: # new in 2.23
76
+ Enabled: true
77
+ RSpec/BeEmpty: # new in 2.20
78
+ Enabled: true
79
+ RSpec/ContainExactly: # new in 2.19
80
+ Enabled: true
81
+ RSpec/IndexedLet: # new in 2.20
82
+ Enabled: true
83
+ RSpec/MatchArray: # new in 2.19
84
+ Enabled: true
data/.rubocop.yml CHANGED
@@ -3,12 +3,16 @@ inherit_mode:
3
3
  - Exclude
4
4
 
5
5
  require:
6
+ - standard
7
+ - standard-custom
8
+ - standard-performance
6
9
  - rubocop-performance
7
10
  - rubocop-rspec
8
- - standard
9
11
 
10
12
  inherit_gem:
11
13
  standard: config/base.yml
14
+ standard-performance: config/base.yml
15
+ standard-custom: config/base.yml
12
16
 
13
17
  inherit_from:
14
18
  - .rubocop/custom.yml
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- folio_client (0.11.0)
4
+ folio_client (0.12.0)
5
5
  activesupport (>= 4.2, < 8)
6
6
  dry-monads
7
7
  faraday
@@ -11,82 +11,92 @@ PATH
11
11
  GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
- activesupport (7.0.4.3)
14
+ activesupport (7.0.8)
15
15
  concurrent-ruby (~> 1.0, >= 1.0.2)
16
16
  i18n (>= 1.6, < 2)
17
17
  minitest (>= 5.1)
18
18
  tzinfo (~> 2.0)
19
- addressable (2.8.1)
19
+ addressable (2.8.5)
20
20
  public_suffix (>= 2.0.2, < 6.0)
21
21
  ast (2.4.2)
22
+ base64 (0.1.1)
22
23
  byebug (11.1.3)
23
24
  concurrent-ruby (1.2.2)
24
25
  crack (0.4.5)
25
26
  rexml
26
27
  diff-lcs (1.5.0)
27
28
  docile (1.4.0)
28
- dry-core (1.0.0)
29
+ dry-core (1.0.1)
29
30
  concurrent-ruby (~> 1.0)
30
31
  zeitwerk (~> 2.6)
31
32
  dry-monads (1.6.0)
32
33
  concurrent-ruby (~> 1.0)
33
34
  dry-core (~> 1.0, < 2)
34
35
  zeitwerk (~> 2.6)
35
- faraday (2.7.4)
36
+ faraday (2.7.11)
37
+ base64
36
38
  faraday-net_http (>= 2.0, < 3.1)
37
39
  ruby2_keywords (>= 0.0.4)
38
40
  faraday-net_http (3.0.2)
39
41
  hashdiff (1.0.1)
40
- i18n (1.12.0)
42
+ i18n (1.14.1)
41
43
  concurrent-ruby (~> 1.0)
42
44
  json (2.6.3)
43
45
  language_server-protocol (3.17.0.3)
46
+ lint_roller (1.1.0)
44
47
  marc (1.2.0)
45
48
  rexml
46
49
  scrub_rb (>= 1.0.1, < 2)
47
50
  unf
48
- minitest (5.18.0)
49
- parallel (1.22.1)
50
- parser (3.2.1.1)
51
+ minitest (5.20.0)
52
+ parallel (1.23.0)
53
+ parser (3.2.2.3)
51
54
  ast (~> 2.4.1)
52
- public_suffix (5.0.1)
55
+ racc
56
+ public_suffix (5.0.3)
57
+ racc (1.7.1)
53
58
  rainbow (3.1.1)
54
59
  rake (13.0.6)
55
- regexp_parser (2.7.0)
56
- rexml (3.2.5)
60
+ regexp_parser (2.8.1)
61
+ rexml (3.2.6)
57
62
  rspec (3.12.0)
58
63
  rspec-core (~> 3.12.0)
59
64
  rspec-expectations (~> 3.12.0)
60
65
  rspec-mocks (~> 3.12.0)
61
- rspec-core (3.12.1)
66
+ rspec-core (3.12.2)
62
67
  rspec-support (~> 3.12.0)
63
- rspec-expectations (3.12.2)
68
+ rspec-expectations (3.12.3)
64
69
  diff-lcs (>= 1.2.0, < 2.0)
65
70
  rspec-support (~> 3.12.0)
66
- rspec-mocks (3.12.4)
71
+ rspec-mocks (3.12.6)
67
72
  diff-lcs (>= 1.2.0, < 2.0)
68
73
  rspec-support (~> 3.12.0)
69
- rspec-support (3.12.0)
70
- rubocop (1.48.1)
74
+ rspec-support (3.12.1)
75
+ rubocop (1.56.3)
76
+ base64 (~> 0.1.1)
71
77
  json (~> 2.3)
78
+ language_server-protocol (>= 3.17.0)
72
79
  parallel (~> 1.10)
73
- parser (>= 3.2.0.0)
80
+ parser (>= 3.2.2.3)
74
81
  rainbow (>= 2.2.2, < 4.0)
75
82
  regexp_parser (>= 1.8, < 3.0)
76
83
  rexml (>= 3.2.5, < 4.0)
77
- rubocop-ast (>= 1.26.0, < 2.0)
84
+ rubocop-ast (>= 1.28.1, < 2.0)
78
85
  ruby-progressbar (~> 1.7)
79
86
  unicode-display_width (>= 2.4.0, < 3.0)
80
- rubocop-ast (1.28.0)
87
+ rubocop-ast (1.29.0)
81
88
  parser (>= 3.2.1.0)
82
- rubocop-capybara (2.17.1)
89
+ rubocop-capybara (2.18.0)
83
90
  rubocop (~> 1.41)
84
- rubocop-performance (1.16.0)
91
+ rubocop-factory_bot (2.24.0)
92
+ rubocop (~> 1.33)
93
+ rubocop-performance (1.19.1)
85
94
  rubocop (>= 1.7.0, < 2.0)
86
95
  rubocop-ast (>= 0.4.0)
87
- rubocop-rspec (2.19.0)
96
+ rubocop-rspec (2.24.0)
88
97
  rubocop (~> 1.33)
89
98
  rubocop-capybara (~> 2.17)
99
+ rubocop-factory_bot (~> 2.22)
90
100
  ruby-progressbar (1.13.0)
91
101
  ruby2_keywords (0.0.5)
92
102
  scrub_rb (1.0.1)
@@ -96,21 +106,29 @@ GEM
96
106
  simplecov_json_formatter (~> 0.1)
97
107
  simplecov-html (0.12.3)
98
108
  simplecov_json_formatter (0.1.4)
99
- standard (1.25.3)
109
+ standard (1.31.1)
100
110
  language_server-protocol (~> 3.17.0.2)
101
- rubocop (~> 1.48.1)
102
- rubocop-performance (~> 1.16.0)
111
+ lint_roller (~> 1.0)
112
+ rubocop (~> 1.56.2)
113
+ standard-custom (~> 1.0.0)
114
+ standard-performance (~> 1.2)
115
+ standard-custom (1.0.2)
116
+ lint_roller (~> 1.0)
117
+ rubocop (~> 1.50)
118
+ standard-performance (1.2.0)
119
+ lint_roller (~> 1.1)
120
+ rubocop-performance (~> 1.19.0)
103
121
  tzinfo (2.0.6)
104
122
  concurrent-ruby (~> 1.0)
105
123
  unf (0.1.4)
106
124
  unf_ext
107
125
  unf_ext (0.0.8.2)
108
126
  unicode-display_width (2.4.2)
109
- webmock (3.18.1)
127
+ webmock (3.19.1)
110
128
  addressable (>= 2.8.0)
111
129
  crack (>= 0.3.2)
112
130
  hashdiff (>= 0.4.0, < 2.0.0)
113
- zeitwerk (2.6.7)
131
+ zeitwerk (2.6.11)
114
132
 
115
133
  PLATFORMS
116
134
  x86_64-darwin-19
@@ -130,4 +148,4 @@ DEPENDENCIES
130
148
  webmock
131
149
 
132
150
  BUNDLED WITH
133
- 2.4.5
151
+ 2.4.13
data/README.md CHANGED
@@ -71,15 +71,15 @@ client.fetch_marc_hash(instance_hrid: "a7927874")
71
71
  [{"003"=>"FOLIO"}....]
72
72
  }
73
73
 
74
- # Import a MARC record into FOLIO
75
- data_importer = client.data_import(marc: my_marc, job_profile_id: '4ba4f4ab', job_profile_name: 'ETDs')
74
+ # Import MARC records into FOLIO
75
+ data_importer = client.data_import(records: [marc_record1, marc_record2], job_profile_id: '4ba4f4ab', job_profile_name: 'ETDs')
76
76
  # If called too quickly, might get Failure(:not_found)
77
77
  data_importer.status
78
78
  => Failure(:pending)
79
79
  data_importer.wait_until_complete
80
80
  => Success()
81
- data_importer.instance_hrid
82
- => Success("in00000000010")
81
+ data_importer.instance_hrids
82
+ => Success(["in00000000010", "in00000000011"])
83
83
 
84
84
  # Get list of organizations (filtered with an optional query)
85
85
  # see https://s3.amazonaws.com/foliodocs/api/mod-organizations/p/organizations.html#organizations_organizations_get
@@ -14,17 +14,21 @@ class FolioClient
14
14
  @client = client
15
15
  end
16
16
 
17
- # @param record [MARC::Record] record to be imported
17
+ # @param records [Array<MARC::Record>] records to be imported
18
18
  # @param job_profile_id [String] job profile id to use for import
19
19
  # @param job_profile_name [String] job profile name to use for import
20
20
  # @return [JobStatus] a job status instance to get information about the data import job
21
- def import(marc:, job_profile_id:, job_profile_name:)
21
+ def import(records:, job_profile_id:, job_profile_name:)
22
22
  response_hash = client.post("/data-import/uploadDefinitions", {fileDefinitions: [{name: marc_filename}]})
23
23
  upload_definition_id = response_hash.dig("fileDefinitions", 0, "uploadDefinitionId")
24
24
  job_execution_id = response_hash.dig("fileDefinitions", 0, "jobExecutionId")
25
25
  file_definition_id = response_hash.dig("fileDefinitions", 0, "id")
26
26
 
27
- upload_file_response_hash = client.post("/data-import/uploadDefinitions/#{upload_definition_id}/files/#{file_definition_id}", marc_binary(marc), content_type: "application/octet-stream")
27
+ upload_file_response_hash = client.post(
28
+ "/data-import/uploadDefinitions/#{upload_definition_id}/files/#{file_definition_id}",
29
+ marc_binary(records),
30
+ content_type: "application/octet-stream"
31
+ )
28
32
 
29
33
  client.post(
30
34
  "/data-import/uploadDefinitions/#{upload_definition_id}/processFiles",
@@ -51,16 +55,16 @@ class FolioClient
51
55
 
52
56
  private
53
57
 
54
- attr_reader :client, :marc, :job_profile_id, :job_profile_name
58
+ attr_reader :client, :job_profile_id, :job_profile_name
55
59
 
56
60
  def marc_filename
57
61
  @marc_filename ||= "#{DateTime.now.iso8601}.marc"
58
62
  end
59
63
 
60
- def marc_binary(marc)
64
+ def marc_binary(records)
61
65
  StringIO.open do |io|
62
66
  MARC::Writer.new(io) do |writer|
63
- writer.write(marc)
67
+ records.each { |record| writer.write(record) }
64
68
  end
65
69
  io.string
66
70
  end
@@ -17,15 +17,17 @@ class FolioClient
17
17
  @job_execution_id = job_execution_id
18
18
  end
19
19
 
20
- # @return [Dry::Monads::Result] Success if job is complete,
21
- # Failure(:pending) if job is still running,
22
- # Failure(:error) if job has errors
23
- # Failure(:not_found) if job is not found
20
+ # @todo An "ERROR" approach means one or more records failed, but it does
21
+ # not mean they all fail. We will likely need a more nuanced way to
22
+ # handle this eventually.
23
+ #
24
+ # @return [Dry::Monads::Result] Success() if job is complete,
25
+ # Failure(:pending) if job is still running,
26
+ # Failure(:not_found) if job is not found
24
27
  def status
25
- response_hash = client.get("/metadata-provider/jobSummary/#{job_execution_id}")
28
+ response_hash = client.get("/change-manager/jobExecutions/#{job_execution_id}")
26
29
 
27
- return Failure(:error) if response_hash["totalErrors"].positive?
28
- return Failure(:pending) if response_hash.dig("sourceRecordSummary", "totalCreatedEntities").zero? && response_hash.dig("sourceRecordSummary", "totalUpdatedEntities").zero?
30
+ return Failure(:pending) if !["COMMITTED", "ERROR"].include?(response_hash["status"])
29
31
 
30
32
  Success()
31
33
  rescue ResourceNotFound
@@ -37,18 +39,18 @@ class FolioClient
37
39
  wait_with_timeout(wait_secs: wait_secs, timeout_secs: timeout_secs) { status }
38
40
  end
39
41
 
40
- def instance_hrid
42
+ def instance_hrids
41
43
  current_status = status
42
44
  return current_status unless current_status.success?
43
45
 
44
- @instance_hrid ||= wait_with_timeout do
46
+ @instance_hrids ||= wait_with_timeout do
45
47
  response = client
46
48
  .get("/metadata-provider/journalRecords/#{job_execution_id}")
47
49
  .fetch("journalRecords", [])
48
- .find { |journal_record| journal_record["entityType"] == "INSTANCE" }
49
- &.fetch("entityHrId", nil)
50
+ .select { |journal_record| journal_record["entityType"] == "INSTANCE" && journal_record["actionStatus"] == "COMPLETED" }
51
+ .filter_map { |instance_record| instance_record["entityHrId"] }
50
52
 
51
- response.nil? ? Failure() : Success(response)
53
+ response.empty? ? Failure() : Success(response)
52
54
  end
53
55
  end
54
56
 
@@ -61,7 +63,7 @@ class FolioClient
61
63
  end
62
64
 
63
65
  def default_timeout_secs
64
- 5 * 60
66
+ 10 * 60
65
67
  end
66
68
 
67
69
  def wait_with_timeout(wait_secs: default_wait_secs, timeout_secs: default_timeout_secs)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class FolioClient
4
- VERSION = "0.11.0"
4
+ VERSION = "0.12.0"
5
5
  end
data/lib/folio_client.rb CHANGED
@@ -47,25 +47,34 @@ class FolioClient
47
47
  # @param url [String] the folio API URL
48
48
  # @param login_params [Hash] the folio client login params (username:, password:)
49
49
  # @param okapi_headers [Hash] the okapi specific headers to add (X-Okapi-Tenant:, User-Agent:)
50
+ # @return [FolioClient] the configured Singleton class
50
51
  def configure(url:, login_params:, okapi_headers:, timeout: default_timeout)
51
52
  instance.config = OpenStruct.new(
53
+ # For the initial token, use a dummy value to avoid hitting any APIs
54
+ # during configuration, allowing `with_token_refresh_when_unauthorized` to handle
55
+ # auto-magic token refreshing. Why not immediately get a valid token? Our apps
56
+ # commonly invoke client `.configure` methods in the initializer in all
57
+ # application environments, even those that are never expected to
58
+ # connect to production APIs, such as local development machines.
59
+ #
60
+ # NOTE: `nil` and blank string cannot be used as dummy values here as
61
+ # they lead to a malformed request to be sent, which triggers an
62
+ # exception not rescued by `with_token_refresh_when_unauthorized`
63
+ token: "a temporary dummy token to avoid hitting the API before it is needed",
52
64
  url: url,
53
65
  login_params: login_params,
54
66
  okapi_headers: okapi_headers,
55
67
  timeout: timeout
56
68
  )
57
69
 
58
- # NOTE: The token cannot be set above, since `#connection` relies on
59
- # `instance.config` parameters having already been set.
60
- instance.config.token = Authenticator.token(login_params, connection)
61
-
62
70
  self
63
71
  end
64
72
 
65
- delegate :config, :connection, :data_import, :default_timeout, :edit_marc_json,
66
- :fetch_external_id, :fetch_hrid, :fetch_instance_info, :fetch_marc_hash, :get,
67
- :has_instance_status?, :interface_details, :job_profiles, :organization_interfaces,
68
- :organizations, :post, :put, to: :instance
73
+ delegate :config, :connection, :data_import, :default_timeout,
74
+ :edit_marc_json, :fetch_external_id, :fetch_hrid, :fetch_instance_info,
75
+ :fetch_marc_hash, :get, :has_instance_status?, :http_get_headers,
76
+ :http_post_and_put_headers, :interface_details, :job_profiles,
77
+ :organization_interfaces, :organizations, :post, :put, to: :instance
69
78
  end
70
79
 
71
80
  attr_accessor :config
@@ -74,7 +83,7 @@ class FolioClient
74
83
  # @param path [String] the path to the Folio API request
75
84
  # @param params [Hash] params to get to the API
76
85
  def get(path, params = {})
77
- response = TokenWrapper.refresh(config, connection) do
86
+ response = with_token_refresh_when_unauthorized do
78
87
  connection.get(path, params, {"x-okapi-token": config.token})
79
88
  end
80
89
 
@@ -91,7 +100,7 @@ class FolioClient
91
100
  # @param body [Object] body to post to the API as JSON
92
101
  def post(path, body = nil, content_type: "application/json")
93
102
  req_body = (content_type == "application/json") ? body&.to_json : body
94
- response = TokenWrapper.refresh(config, connection) do
103
+ response = with_token_refresh_when_unauthorized do
95
104
  req_headers = {
96
105
  "x-okapi-token": config.token,
97
106
  "content-type": content_type
@@ -112,7 +121,7 @@ class FolioClient
112
121
  # @param body [Object] body to put to the API as JSON
113
122
  def put(path, body = nil, content_type: "application/json")
114
123
  req_body = (content_type == "application/json") ? body&.to_json : body
115
- response = TokenWrapper.refresh(config, connection) do
124
+ response = with_token_refresh_when_unauthorized do
116
125
  req_headers = {
117
126
  "x-okapi-token": config.token,
118
127
  "content-type": content_type
@@ -218,4 +227,30 @@ class FolioClient
218
227
  def default_timeout
219
228
  120
220
229
  end
230
+
231
+ private
232
+
233
+ # Wraps API operations to request new access token if expired.
234
+ # @yieldreturn response [Faraday::Response] the response to inspect
235
+ #
236
+ # @note You likely want to make sure you're wrapping a _single_ HTTP request in this
237
+ # method, because 1) all calls in the block will be retried from the top if there's
238
+ # an authN failure detected, and 2) only the response returned by the block will be
239
+ # inspected for authN failure.
240
+ # Related: consider that the client instance and its token will live across many
241
+ # invocations of the FolioClient methods once the client is configured by a consuming application,
242
+ # since this class is a Singleton. Thus, a token may expire between any two calls (i.e. it
243
+ # isn't necessary for a set of operations to collectively take longer than the token lifetime for
244
+ # expiry to fall in the middle of that related set of HTTP calls).
245
+ def with_token_refresh_when_unauthorized
246
+ response = yield
247
+
248
+ # if unauthorized, token has likely expired. try to get a new token and then retry the same request(s).
249
+ if response.status == 401
250
+ config.token = Authenticator.token(config.login_params, connection)
251
+ response = yield
252
+ end
253
+
254
+ response
255
+ end
221
256
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: folio_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Mangiafico
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-04-04 00:00:00.000000000 Z
11
+ date: 2023-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -196,7 +196,6 @@ files:
196
196
  - lib/folio_client/organizations.rb
197
197
  - lib/folio_client/records_editor.rb
198
198
  - lib/folio_client/source_storage.rb
199
- - lib/folio_client/token_wrapper.rb
200
199
  - lib/folio_client/unexpected_response.rb
201
200
  - lib/folio_client/version.rb
202
201
  homepage: https://github.com/sul-dlss/folio_client
@@ -206,7 +205,7 @@ metadata:
206
205
  source_code_uri: https://github.com/sul-dlss/folio_client
207
206
  changelog_uri: https://github.com/sul-dlss/folio_client/releases
208
207
  rubygems_mfa_required: 'true'
209
- post_install_message:
208
+ post_install_message:
210
209
  rdoc_options: []
211
210
  require_paths:
212
211
  - lib
@@ -222,7 +221,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
222
221
  version: '0'
223
222
  requirements: []
224
223
  rubygems_version: 3.3.7
225
- signing_key:
224
+ signing_key:
226
225
  specification_version: 4
227
226
  summary: Interface for interacting with the Folio ILS API.
228
227
  test_files: []
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class FolioClient
4
- # Wraps API operations to request new access token if expired
5
- class TokenWrapper
6
- def self.refresh(config, connection)
7
- yield.tap { |response| UnexpectedResponse.call(response) unless response.success? }
8
- rescue UnauthorizedError
9
- config.token = Authenticator.token(config.login_params, connection)
10
- yield
11
- end
12
- end
13
- end