folio_client 0.12.0 → 0.14.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: 7918be772bc1758840166cbb6f0fb66bfbf4765f636118d971efef2192a947df
4
- data.tar.gz: 86d3c7e5656e849cf3358ddf7e22463bd65527cedf017a9a31dfdd2606bad88a
3
+ metadata.gz: 52b3024a210528d439f1d65a9e8a0b62b1b5359d0ae639612f46b7f2808759e2
4
+ data.tar.gz: 168ccfccfa8155171bd0ccba099ad91bd16533ea148b87867f6df3fd3aa617fb
5
5
  SHA512:
6
- metadata.gz: 9471247fec95c9df775cd359896c788d124173477b74f1124d41641f76e6d61438fe7b5e7c10fb3ee7d6efb9f5dba11c9b0b7b45fb9040520f6668cba626fc1d
7
- data.tar.gz: 4f0adf00bb277b709a68552e7f2b5119e7b8597723ffc3c4f500d850e2c8470df0249a19e35a98bcfcf2ef6daa3befb8155e57d5f69c8d825fe3b1806cd240a5
6
+ metadata.gz: 618c561b2f7f69baa03733e9a4f1cca3cf50e3d2bdc98924a9d759639634e98fc2f27f8868c8876eab034da6963976d58e54d396f39379f9e9223a762584490a
7
+ data.tar.gz: f0ddf15d1b38e14f3e8b506fbf6aa6249b05c77c35192c7a0315307e6ffe48c586ed66863f200279360217f8edc15f705c8d83b0d7c0c710a1ab9b047ec35f6f
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- folio_client (0.12.0)
4
+ folio_client (0.14.0)
5
5
  activesupport (>= 4.2, < 8)
6
6
  dry-monads
7
7
  faraday
@@ -11,21 +11,30 @@ PATH
11
11
  GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
- activesupport (7.0.8)
14
+ activesupport (7.1.1)
15
+ base64
16
+ bigdecimal
15
17
  concurrent-ruby (~> 1.0, >= 1.0.2)
18
+ connection_pool (>= 2.2.5)
19
+ drb
16
20
  i18n (>= 1.6, < 2)
17
21
  minitest (>= 5.1)
22
+ mutex_m
18
23
  tzinfo (~> 2.0)
19
24
  addressable (2.8.5)
20
25
  public_suffix (>= 2.0.2, < 6.0)
21
26
  ast (2.4.2)
22
27
  base64 (0.1.1)
28
+ bigdecimal (3.1.4)
23
29
  byebug (11.1.3)
24
30
  concurrent-ruby (1.2.2)
31
+ connection_pool (2.4.1)
25
32
  crack (0.4.5)
26
33
  rexml
27
34
  diff-lcs (1.5.0)
28
35
  docile (1.4.0)
36
+ drb (2.1.1)
37
+ ruby2_keywords
29
38
  dry-core (1.0.1)
30
39
  concurrent-ruby (~> 1.0)
31
40
  zeitwerk (~> 2.6)
@@ -49,15 +58,16 @@ GEM
49
58
  scrub_rb (>= 1.0.1, < 2)
50
59
  unf
51
60
  minitest (5.20.0)
61
+ mutex_m (0.1.2)
52
62
  parallel (1.23.0)
53
- parser (3.2.2.3)
63
+ parser (3.2.2.4)
54
64
  ast (~> 2.4.1)
55
65
  racc
56
66
  public_suffix (5.0.3)
57
- racc (1.7.1)
67
+ racc (1.7.3)
58
68
  rainbow (3.1.1)
59
- rake (13.0.6)
60
- regexp_parser (2.8.1)
69
+ rake (13.1.0)
70
+ regexp_parser (2.8.2)
61
71
  rexml (3.2.6)
62
72
  rspec (3.12.0)
63
73
  rspec-core (~> 3.12.0)
@@ -72,7 +82,7 @@ GEM
72
82
  diff-lcs (>= 1.2.0, < 2.0)
73
83
  rspec-support (~> 3.12.0)
74
84
  rspec-support (3.12.1)
75
- rubocop (1.56.3)
85
+ rubocop (1.56.4)
76
86
  base64 (~> 0.1.1)
77
87
  json (~> 2.3)
78
88
  language_server-protocol (>= 3.17.0)
@@ -84,17 +94,17 @@ GEM
84
94
  rubocop-ast (>= 1.28.1, < 2.0)
85
95
  ruby-progressbar (~> 1.7)
86
96
  unicode-display_width (>= 2.4.0, < 3.0)
87
- rubocop-ast (1.29.0)
97
+ rubocop-ast (1.30.0)
88
98
  parser (>= 3.2.1.0)
89
- rubocop-capybara (2.18.0)
99
+ rubocop-capybara (2.19.0)
90
100
  rubocop (~> 1.41)
91
101
  rubocop-factory_bot (2.24.0)
92
102
  rubocop (~> 1.33)
93
103
  rubocop-performance (1.19.1)
94
104
  rubocop (>= 1.7.0, < 2.0)
95
105
  rubocop-ast (>= 0.4.0)
96
- rubocop-rspec (2.24.0)
97
- rubocop (~> 1.33)
106
+ rubocop-rspec (2.25.0)
107
+ rubocop (~> 1.40)
98
108
  rubocop-capybara (~> 2.17)
99
109
  rubocop-factory_bot (~> 2.22)
100
110
  ruby-progressbar (1.13.0)
@@ -106,29 +116,29 @@ GEM
106
116
  simplecov_json_formatter (~> 0.1)
107
117
  simplecov-html (0.12.3)
108
118
  simplecov_json_formatter (0.1.4)
109
- standard (1.31.1)
119
+ standard (1.31.2)
110
120
  language_server-protocol (~> 3.17.0.2)
111
121
  lint_roller (~> 1.0)
112
- rubocop (~> 1.56.2)
122
+ rubocop (~> 1.56.4)
113
123
  standard-custom (~> 1.0.0)
114
124
  standard-performance (~> 1.2)
115
125
  standard-custom (1.0.2)
116
126
  lint_roller (~> 1.0)
117
127
  rubocop (~> 1.50)
118
- standard-performance (1.2.0)
128
+ standard-performance (1.2.1)
119
129
  lint_roller (~> 1.1)
120
- rubocop-performance (~> 1.19.0)
130
+ rubocop-performance (~> 1.19.1)
121
131
  tzinfo (2.0.6)
122
132
  concurrent-ruby (~> 1.0)
123
133
  unf (0.1.4)
124
134
  unf_ext
125
135
  unf_ext (0.0.8.2)
126
- unicode-display_width (2.4.2)
136
+ unicode-display_width (2.5.0)
127
137
  webmock (3.19.1)
128
138
  addressable (>= 2.8.0)
129
139
  crack (>= 0.3.2)
130
140
  hashdiff (>= 0.4.0, < 2.0.0)
131
- zeitwerk (2.6.11)
141
+ zeitwerk (2.6.12)
132
142
 
133
143
  PLATFORMS
134
144
  x86_64-darwin-19
data/README.md CHANGED
@@ -123,6 +123,47 @@ client.interface_details(id: 'c6f7470e-6229-45ce-b3f9-32006e9affcf')
123
123
  "createdByUserId"=>"38524916-598d-4edf-a2ef-04bba7e78ad6",
124
124
  "updatedDate"=>"2023-02-16T22:27:51.515+00:00",
125
125
  "updatedByUserId"=>"38524916-598d-4edf-a2ef-04bba7e78ad6"}}
126
+
127
+ # Get list of users (filtered with an optional query)
128
+ # see https://s3.amazonaws.com/foliodocs/api/mod-users/r/users.html#users_get
129
+ client.users(query: 'username=="test*"')
130
+ => {"users"=>
131
+ [{"username"=>"testing",
132
+ "id"=>"bbbadd51-c2f1-4107-a54d-52b39087725c",
133
+ "externalSystemId"=>"00324439",
134
+ "barcode"=>"2559202566",
135
+ "active"=>false,
136
+ "departments"=>[],
137
+ "proxyFor"=>[],
138
+ "personal"=>
139
+ {"lastName"=>"Testing",
140
+ "firstName"=>"Test",
141
+ "email"=>"foliotesting@lists.stanford.edu",
142
+ "addresses"=>
143
+ [{"countryId"=>"US",
144
+ "addressLine1"=>"13 Fake St",
145
+ "city"=>"Palo Alto",
146
+ "region"=>"California",
147
+ "postalCode"=>"94301",
148
+ "addressTypeId"=>"93d3d88d-499b-45d0-9bc7-ac73c3a19880",
149
+ "primaryAddress"=>true}]},
150
+ "createdDate"=>"2023-10-01T08:50:37.203+00:00",
151
+ "updatedDate"=>"2023-10-01T08:50:37.203+00:00",
152
+ "metadata"=>
153
+ {"createdDate"=>"2023-09-02T02:51:43.448+00:00",
154
+ "createdByUserId"=>"58d0aaf6-dcda-4d5e-92da-012e6b7dd766",
155
+ "updatedDate"=>"2023-10-01T08:50:37.196+00:00",
156
+ "updatedByUserId"=>"58d0aaf6-dcda-4d5e-92da-012e6b7dd766"},
157
+ "customFields"=>{"affiliation"=>"affiliate:sponsored"}}],
158
+ "totalRecords"=>1,
159
+ "resultInfo"=>{"totalRecords"=>1, "facets"=>[], "diagnostics"=>[]}}
160
+
161
+ # Get specific user info
162
+ # see https://s3.amazonaws.com/foliodocs/api/mod-users/r/users.html#users_get
163
+ client.user_details(id: 'bbbadd51-c2f1-4107-a54d-52b39087725c')
164
+ => {"username"=>"testing",
165
+ "id"=>"bbbadd51-c2f1-4107-a54d-52b39087725c",
166
+ "externalSystemId"=>"00324439", ... # same response as above, but for single user
126
167
  ```
127
168
 
128
169
  ## Development
@@ -131,6 +172,22 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
131
172
 
132
173
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
133
174
 
175
+ ## Integration Testing
176
+
177
+ To test that the gem works against the Folio APIs, run `api_test.rb` via:
178
+
179
+ ```shell
180
+ # NOTE: This is bash syntax, YMMV
181
+ $ export OKAPI_PASSWORD=$(vault kv get --field=content puppet/application/folio/stage/app_sdr_password)
182
+ $ export OKAPI_TENANT=sul
183
+ $ export OKAPI_USER=app_sdr
184
+ $ export OKAPI_URL=https://okapi-stage.stanford.edu
185
+ # NOTE: The args below are a list of MARC files
186
+ $ bundle exec ruby ./api_test.rb /path/to/marc/files/test.mrc /another/marc/file/at/foobar.marc
187
+ ```
188
+
189
+ Inspect the output and make sure there are no errors.
190
+
134
191
  ## Contributing
135
192
 
136
193
  Bug reports and pull requests are welcome on GitHub at https://github.com/sul-dlss/folio_client.
data/api_test.rb ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "folio_client"
5
+
6
+ marc_files = *ARGV
7
+
8
+ client =
9
+ FolioClient.configure(
10
+ url: ENV["OKAPI_URL"],
11
+ login_params: {
12
+ username: ENV["OKAPI_USER"],
13
+ password: ENV["OKAPI_PASSWORD"]
14
+ },
15
+ okapi_headers: {
16
+ "X-Okapi-Tenant": ENV["OKAPI_TENANT"],
17
+ "User-Agent": "folio_client gem (testing)"
18
+ }
19
+ )
20
+
21
+ pp(client.fetch_marc_hash(instance_hrid: "a666"))
22
+
23
+ puts client.fetch_marc_xml(instance_hrid: "a666")
24
+ puts client.fetch_marc_xml(barcode: "20503330279")
25
+
26
+ puts client.users(query: 'username=="pet*"')
27
+
28
+ records = marc_files.flat_map do |marc_file_path|
29
+ MARC::Reader.new(marc_file_path).to_a
30
+ end
31
+
32
+ data_importer =
33
+ client.data_import(
34
+ records: records,
35
+ job_profile_id: "e34d7b92-9b83-11eb-a8b3-0242ac130003",
36
+ job_profile_name: "Default - Create instance and SRS MARC Bib"
37
+ )
38
+
39
+ puts data_importer.wait_until_complete
40
+ puts data_importer.instance_hrids
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "date"
4
- require "marc"
5
4
  require "stringio"
6
5
 
7
6
  class FolioClient
@@ -3,6 +3,8 @@
3
3
  class FolioClient
4
4
  # Lookup records in Folio Source Storage
5
5
  class SourceStorage
6
+ FIELDS_TO_REMOVE = %w[001 003].freeze
7
+
6
8
  attr_accessor :client
7
9
 
8
10
  # @param client [FolioClient] the configured client
@@ -24,5 +26,36 @@ class FolioClient
24
26
 
25
27
  response_hash["sourceRecords"].first["parsedRecord"]["content"]
26
28
  end
29
+
30
+ # get marc bib data as MARCXML from folio given an instance HRID
31
+ # @param instance_hrid [String] the instance HRID to use for MARC lookup
32
+ # @param barcode [String] the barcode to use for MARC lookup
33
+ # @return [String] MARCXML string
34
+ # @raise [ResourceNotFound]
35
+ # @raise [MultipleResourcesFound]
36
+ def fetch_marc_xml(instance_hrid: nil, barcode: nil)
37
+ raise ArgumentError, "Either a barcode or a Folio instance HRID must be provided" if barcode.nil? && instance_hrid.nil?
38
+
39
+ instance_hrid ||= client.fetch_hrid(barcode: barcode)
40
+
41
+ raise ResourceNotFound, "Catalog record not found. HRID: #{instance_hrid} | Barcode: #{barcode}" if instance_hrid.blank?
42
+
43
+ marc_record = MARC::Record.new_from_hash(
44
+ fetch_marc_hash(instance_hrid: instance_hrid)
45
+ )
46
+ updated_marc = MARC::Record.new
47
+ updated_marc.leader = marc_record.leader
48
+ marc_record.fields.each do |field|
49
+ # explicitly remove all listed tags from the record
50
+ next if FIELDS_TO_REMOVE.include?(field.tag)
51
+
52
+ updated_marc.fields << field
53
+ end
54
+ # explicitly inject the instance_hrid into the 001 field
55
+ updated_marc.fields << MARC::ControlField.new("001", instance_hrid)
56
+ # explicitly inject FOLIO into the 003 field
57
+ updated_marc.fields << MARC::ControlField.new("003", "FOLIO")
58
+ updated_marc.to_xml.to_s
59
+ end
27
60
  end
28
61
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ class FolioClient
4
+ # Query user records in Folio; see
5
+ # https://s3.amazonaws.com/foliodocs/api/mod-users/r/users.html
6
+ class Users
7
+ attr_accessor :client
8
+
9
+ # @param client [FolioClient] the configured client
10
+ def initialize(client)
11
+ @client = client
12
+ end
13
+
14
+ # @param query [String] an optional query to limit the number of users returned
15
+ # @param limit [Integer] the number of results to return (defaults to 10,000)
16
+ # @param offset [Integer] the offset for results returned (defaults to 0)
17
+ # @param lang [String] language code for returned results (defaults to 'en')
18
+ def fetch_list(query: nil, limit: 10000, offset: 0, lang: "en")
19
+ params = {limit: limit, offset: offset, lang: lang}
20
+ params[:query] = query if query
21
+ client.get("/users", params)
22
+ end
23
+
24
+ # @param id [String] id for requested user
25
+ # @param lang [String] language code for returned results (defaults to 'en')
26
+ def fetch_user_details(id:, lang: "en")
27
+ client.get("/users/#{id}", {
28
+ lang: lang
29
+ })
30
+ end
31
+ end
32
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class FolioClient
4
- VERSION = "0.12.0"
4
+ VERSION = "0.14.0"
5
5
  end
data/lib/folio_client.rb CHANGED
@@ -3,8 +3,9 @@
3
3
  require "active_support/core_ext/module/delegation"
4
4
  require "active_support/core_ext/object/blank"
5
5
  require "faraday"
6
- require "singleton"
6
+ require "marc"
7
7
  require "ostruct"
8
+ require "singleton"
8
9
  require "zeitwerk"
9
10
 
10
11
  # Load the gem's internal dependencies: use Zeitwerk instead of needing to manually require classes
@@ -72,10 +73,11 @@ class FolioClient
72
73
 
73
74
  delegate :config, :connection, :data_import, :default_timeout,
74
75
  :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
78
- end
76
+ :fetch_marc_hash, :fetch_marc_xml, :get, :has_instance_status?,
77
+ :http_get_headers, :http_post_and_put_headers, :interface_details,
78
+ :job_profiles, :organization_interfaces, :organizations, :users, :user_details,
79
+ :post, :put, to:
80
+ :instance end
79
81
 
80
82
  attr_accessor :config
81
83
 
@@ -175,6 +177,13 @@ class FolioClient
175
177
  .fetch_marc_hash(...)
176
178
  end
177
179
 
180
+ # @see SourceStorage#fetch_marc_xml
181
+ def fetch_marc_xml(...)
182
+ SourceStorage
183
+ .new(self)
184
+ .fetch_marc_xml(...)
185
+ end
186
+
178
187
  # @see Inventory#has_instance_status?
179
188
  def has_instance_status?(...)
180
189
  Inventory
@@ -224,6 +233,20 @@ class FolioClient
224
233
  .fetch_interface_details(...)
225
234
  end
226
235
 
236
+ # @see Users#fetch_list
237
+ def users(...)
238
+ Users
239
+ .new(self)
240
+ .fetch_list(...)
241
+ end
242
+
243
+ # @see Users#fetch_user_details
244
+ def user_details(...)
245
+ Users
246
+ .new(self)
247
+ .fetch_user_details(...)
248
+ end
249
+
227
250
  def default_timeout
228
251
  120
229
252
  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.12.0
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Mangiafico
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-09-22 00:00:00.000000000 Z
11
+ date: 2023-11-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -187,6 +187,7 @@ files:
187
187
  - LICENSE
188
188
  - README.md
189
189
  - Rakefile
190
+ - api_test.rb
190
191
  - folio_client.gemspec
191
192
  - lib/folio_client.rb
192
193
  - lib/folio_client/authenticator.rb
@@ -197,6 +198,7 @@ files:
197
198
  - lib/folio_client/records_editor.rb
198
199
  - lib/folio_client/source_storage.rb
199
200
  - lib/folio_client/unexpected_response.rb
201
+ - lib/folio_client/users.rb
200
202
  - lib/folio_client/version.rb
201
203
  homepage: https://github.com/sul-dlss/folio_client
202
204
  licenses: []
@@ -220,7 +222,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
220
222
  - !ruby/object:Gem::Version
221
223
  version: '0'
222
224
  requirements: []
223
- rubygems_version: 3.3.7
225
+ rubygems_version: 3.4.21
224
226
  signing_key:
225
227
  specification_version: 4
226
228
  summary: Interface for interacting with the Folio ILS API.