archivesspace-client 0.4.1 → 0.5.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: 36e35f2fa7f6812ba7b022de156325d3d3b24080a2e2d6c4ccb0dc4b62b4d6b0
4
- data.tar.gz: cf534f96a24a1937664e40265f726f0329fe225168f651aa8126ec4605faf730
3
+ metadata.gz: 324a811c6e310286a30371cda14266b61f11570373aa20baf61b1f54b8e3c8d3
4
+ data.tar.gz: 319354d94ec1fb765a8a811f2ff8273c21342f40fa8e3a5e3c122b4b9af85b92
5
5
  SHA512:
6
- metadata.gz: 9cfb21a793b424ae322f83942b31b398aabf1036b65fee18c1e50bf8b532200ffb232bc87ef017f81ab14f9bb2fc0b5b1f552a42cd7afe62fd1c256ef7c8be8f
7
- data.tar.gz: 3944440ea66c0cd262a94661380f8bd49bf11edf20d55ca17bfb13fe89fcb6e039039802bc86895cc4228eabf8413aada0c3d8efb5f1f8c1d59e2b79aab1d1b7
6
+ metadata.gz: 1ecd05a580e11e19fd50db9b0f0d4ede6ff816d36d8789d50420a1d1275bf9247c5172b932f3ad9627e96655ce27f919d35e6737816650541615cf5efea22c95
7
+ data.tar.gz: 679be0bac6c9a81b685ed233e457d98670e00f834946f57d7ed46091bfd83040c0ee12d0e196bddd00a9bfb88fefc8b0c06170dfd294652b4322b958bfdac4df
@@ -3,15 +3,20 @@ on: [pull_request]
3
3
 
4
4
  jobs:
5
5
  tests:
6
- name: Tests
6
+ name: Tests (Ruby ${{ matrix.ruby }})
7
7
  runs-on: ubuntu-latest
8
+ strategy:
9
+ fail-fast: false
10
+ matrix:
11
+ ruby: ["3.4", "4.0"]
8
12
  steps:
9
13
  - name: Checkout code
10
- uses: actions/checkout@v3
14
+ uses: actions/checkout@v4
11
15
 
12
16
  - name: Setup Ruby and install gems
13
17
  uses: ruby/setup-ruby@v1
14
18
  with:
19
+ ruby-version: ${{ matrix.ruby }}
15
20
  bundler-cache: true
16
21
 
17
22
  - name: Lint
@@ -18,7 +18,6 @@ jobs:
18
18
  uses: ruby/setup-ruby@v1
19
19
  with:
20
20
  bundler-cache: true
21
- ruby-version: 3.2.2
22
21
  rubygems: latest
23
22
 
24
23
  - name: Release Gem
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.2.2
1
+ 4.0.1
data/README.md CHANGED
@@ -1,7 +1,28 @@
1
- # Archivesspace Client
1
+ # ArchivesSpace Client
2
2
 
3
3
  Interact with ArchivesSpace via the API.
4
4
 
5
+ <!-- TOC start (generated with https://github.com/derlin/bitdowntoc) -->
6
+
7
+ * [Installation](#installation)
8
+ * [Usage](#usage)
9
+ * [Configuring a client](#configuring-a-client)
10
+ * [Default configuration](#default-configuration)
11
+ * [Custom configuration, on the fly](#custom-configuration-on-the-fly)
12
+ * [Custom configuration, stored for use with CLI or console](#custom-configuration-stored-for-use-with-cli-or-console)
13
+ * [Making basic requests](#making-basic-requests)
14
+ * [Setting a repository context](#setting-a-repository-context)
15
+ * [Templates](#templates)
16
+ * [CLI](#cli)
17
+ * [Console usage](#console-usage)
18
+ * [Development](#development)
19
+ * [Publishing](#publishing)
20
+ * [Changelog](#changelog)
21
+ * [Contributing](#contributing)
22
+ * [License](#license)
23
+
24
+ <!-- TOC end -->
25
+
5
26
  ## Installation
6
27
 
7
28
  Add this line to your application's Gemfile:
@@ -26,7 +47,9 @@ gem install archivesspace-client
26
47
 
27
48
  See the examples directory for a range of use cases.
28
49
 
29
- **Default configuration**
50
+ ### Configuring a client
51
+
52
+ #### Default configuration
30
53
 
31
54
  Create client with default settings (`localhost:8089`, `admin`, `admin`):
32
55
 
@@ -34,12 +57,11 @@ Create client with default settings (`localhost:8089`, `admin`, `admin`):
34
57
  client = ArchivesSpace::Client.new.login
35
58
  ```
36
59
 
37
- **Custom configuration**
60
+ #### Custom configuration
38
61
 
39
62
  ```ruby
40
63
  config = ArchivesSpace::Configuration.new({
41
- base_uri: "https://archives.university.edu/api",
42
- base_repo: "",
64
+ base_uri: "https://archives.university.edu/staff/api",
43
65
  username: "admin",
44
66
  password: "123456",
45
67
  page_size: 50,
@@ -51,7 +73,32 @@ config = ArchivesSpace::Configuration.new({
51
73
  client = ArchivesSpace::Client.new(config).login
52
74
  ```
53
75
 
54
- **Making basic requests**
76
+ #### Custom configuration, stored for use with CLI or console
77
+
78
+ Create a file containing JSON config data like:
79
+
80
+ ```json
81
+ {
82
+ "base_uri": "http://localhost:4567",
83
+ "username": "admin",
84
+ "password": "myverysecurepassword",
85
+ "page_size": 50,
86
+ "throttle": 0,
87
+ "timeout": 60,
88
+ "verify_ssl": false,
89
+ "debug": true
90
+ }
91
+ ```
92
+
93
+ The CLI and console commands will, by default, look for this stored config at `~/.asclientrc`,
94
+
95
+ However, you may also set a custom location for the file by setting an ASCLIENT_CFG environment variable. This is handy if you prefer to use [XDG Base Directory Specification](https://xdgbasedirectoryspecification.com/), or have other opinions about where such config should live:
96
+
97
+ ```bash
98
+ export ASCLIENT_CFG="$HOME/.config/archivesspace/client.json"
99
+ ```
100
+
101
+ ### Making basic requests
55
102
 
56
103
  The client responds to the standard request methods:
57
104
 
@@ -77,18 +124,46 @@ user = client.users.find { |user| user["username"] == "jdoe" }
77
124
  See `pagination.rb` for endpoints that support record type methods such as
78
125
  `client.digital_objects` etc.
79
126
 
80
- **Setting a repository context**
127
+ ### Setting a repository context
81
128
 
82
129
  Use the `repository` method to add a repository scope to requests (this is optional).
83
130
 
131
+ Instead of doing:
132
+
84
133
  ```ruby
85
- client.repository(2)
86
- client.get('digital_objects', query: {page: 1}) # instead of "repositories/2/digital_objects" etc.
134
+ client.get('repositories/2/digital_objects', query: {page: 1})
135
+ ```
136
+
137
+ You can do:
138
+
139
+ ```ruby
140
+ client.repository(2) do
141
+ client.get('digital_objects', query: {page: 1})
142
+ end
143
+
144
+ # now back in the global scope
145
+ ```
146
+
147
+ Scopes restore the previous context on exit (even if the block raises) and can
148
+ be nested:
149
+
150
+ ```ruby
151
+ client.repository(2) do
152
+ client.repository(3) do
153
+ client.resources # scoped to repo 3
154
+ end
155
+ client.resources # back to repo 2
156
+ end
157
+
158
+ # now back in the global scope
159
+ ```
160
+
161
+ You can also set the scope persistently (without a block) and clear it later:
87
162
 
88
- # to reset
89
- client.repository(nil)
90
- # or
91
- client.use_global_repository
163
+ ```ruby
164
+ client.repository(2)
165
+ client.resources
166
+ client.use_global_repository # or: client.repository(nil)
92
167
  ```
93
168
 
94
169
  ## Templates
@@ -124,26 +199,40 @@ To view available templates use: `ArchivesSpace::Template.list`
124
199
 
125
200
  ## CLI
126
201
 
127
- Create an `~/.asclientrc` file with a json version of the client configuration:
202
+ Create a stored custom configuration to be used with the CLI as described above.
128
203
 
129
- ```json
130
- {
131
- "base_uri": "https://archives.university.edu/api",
132
- "base_repo": "",
133
- "username": "admin",
134
- "password": "123456",
135
- "page_size": 50,
136
- "throttle": 0,
137
- "timeout": 60,
138
- "verify_ssl": false
139
- }
204
+ If you installed this client as a gem via the `gem install archivesspace-client` command, you should be able to use the `asclient` command directly.
205
+
206
+ If entering `asclient` in your terminal returns an error, you will need to use the CLI from within this repository:
207
+
208
+ ```bash
209
+ cd path/to/archivesspace-client
210
+ ./exe/asclient
140
211
  ```
141
212
 
142
- Run commands:
213
+ The `asclient` command is self-documenting and will show you information about the currently supported commands.
214
+
215
+ To get more detailed usage info on a command:
143
216
 
144
217
  ```bash
145
- # when using locally via the repo prefix commands with ./exe/ i.e. ./exe/asclient -v
146
- asclient -v
218
+ asclient exec -h
219
+ ```
220
+
221
+ ## Console usage
222
+
223
+ Loading this application in console allows you to play around with its functionality interactively.
224
+
225
+ Create a stored custom configuration to be used with the console as described above. Then:
226
+
227
+ ```bash
228
+ cd path/to/archivesspace-client
229
+ ./bin/console
230
+ ```
231
+
232
+ An IRB session opens. Entering the following should give you the backend version of the ArchivesSpace instance your stored custom config points to:
233
+
234
+ ```ruby
235
+ @client.backend_version
147
236
  ```
148
237
 
149
238
  ## Development
@@ -169,9 +258,26 @@ bundle exec rake
169
258
  When an updated version (`lib/archivesspace/client/version.rb`) is merged into the
170
259
  main/master branch a new release will be built and published.
171
260
 
261
+ ## Changelog
262
+
263
+ ### 0.5.0
264
+
265
+ Breaking changes:
266
+
267
+ * Removed the `base_repo` configuration option. Use `client.repository(id)` to
268
+ scope requests to a repository instead, either persistently or with a
269
+ block that auto-restores the previous scope.
270
+ * `client.repository(id)` with a block now saves and restores the previous
271
+ context (including when nested or when the block raises), instead of always
272
+ resetting to the global scope.
273
+ * Login failure now raises `ArchivesSpace::AuthenticationError` (was
274
+ `ConnectionError`). `ConnectionError` has been removed.
275
+ * `Client.new` raises `ArchivesSpace::ConfigurationError` (was `RuntimeError`)
276
+ when given a non-`Configuration` argument.
277
+
172
278
  ## Contributing
173
279
 
174
- Bug reports and pull requests are welcome on GitHub at https://github.com/lyrasis/archivesspace-client.
280
+ Bug reports and pull requests are welcome on GitHub at <https://github.com/lyrasis/archivesspace-client>.
175
281
 
176
282
  ## License
177
283
 
@@ -23,15 +23,14 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency "capybara_discoball", "~> 0.1.0"
24
24
  spec.add_development_dependency "json_spec", "~> 1.1", ">= 1.1.5"
25
25
  spec.add_development_dependency "rake", "~> 13.0"
26
- spec.add_development_dependency "rspec", "3.6.0"
27
- spec.add_development_dependency "rubocop", "1.56"
28
- spec.add_development_dependency "standard", "1.31.0"
29
- spec.add_development_dependency "vcr", "6.2.0"
30
- spec.add_development_dependency "webmock", "3.19.1"
26
+ spec.add_development_dependency "rspec", "~> 3.13"
27
+ spec.add_development_dependency "rubocop", "~> 1.72"
28
+ spec.add_development_dependency "standard", "~> 1.44"
29
+ spec.add_development_dependency "vcr", "~> 6.3"
30
+ spec.add_development_dependency "webmock", "~> 3.24"
31
31
 
32
32
  spec.add_dependency "dry-cli", "~> 0.7"
33
33
  spec.add_dependency "httparty", "~> 0.14"
34
34
  spec.add_dependency "json", "~> 2.0"
35
- spec.add_dependency "nokogiri", "~> 1.10"
36
- spec.add_dependency "jbuilder", "~> 2.11.5"
35
+ spec.add_dependency "jbuilder", "~> 2.12"
37
36
  end
data/bin/console CHANGED
@@ -5,15 +5,7 @@ require "bundler/setup"
5
5
  require "archivesspace/client"
6
6
 
7
7
  config = ArchivesSpace::Configuration.new(
8
- {
9
- base_uri: "https://test.archivesspace.org/staff/api",
10
- base_repo: "",
11
- username: "admin",
12
- password: "admin",
13
- page_size: 50,
14
- throttle: 0,
15
- verify_ssl: false
16
- }
8
+ ArchivesSpace::Client::CLI.find_config
17
9
  )
18
10
  @client = ArchivesSpace::Client.new(config).login
19
11
 
data/examples/export.rb CHANGED
@@ -1,14 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
4
- require "awesome_print"
5
4
  require "archivesspace/client"
5
+ require "nokogiri"
6
6
 
7
7
  # official sandbox
8
8
  config = ArchivesSpace::Configuration.new(
9
9
  {
10
10
  base_uri: "https://test.archivesspace.org/staff/api",
11
- base_repo: "",
12
11
  username: "admin",
13
12
  password: "admin",
14
13
  page_size: 50,
@@ -19,17 +18,18 @@ config = ArchivesSpace::Configuration.new(
19
18
 
20
19
  client = ArchivesSpace::Client.new(config).login
21
20
  client.config.throttle = 0.5
22
- client.config.base_repo = "repositories/2"
23
21
 
24
22
  begin
25
- # date -d '2021-02-01 00:00:00' +'%s' # 1612166400
26
- client.resources(query: {modified_since: "1612166400"}).each do |resource|
27
- # for now we are just printing ...
28
- # but you would actually write to a zip file or whatever
29
- id = resource["uri"].split("/")[-1]
30
- opts = {include_unpublished: false}
31
- response = client.get("resource_descriptions/#{id}.xml", opts)
32
- puts Nokogiri::XML(response.body).to_xml
23
+ client.repository 2 do
24
+ # date -d '2021-02-01 00:00:00' +'%s' # 1612166400
25
+ client.resources(query: {modified_since: "1612166400"}).each do |resource|
26
+ # for now we are just printing ...
27
+ # but you would actually write to a zip file or whatever
28
+ id = resource["uri"].split("/")[-1]
29
+ opts = {include_unpublished: false}
30
+ response = client.get("resource_descriptions/#{id}.xml", opts)
31
+ puts Nokogiri::XML(response.body).to_xml
32
+ end
33
33
  end
34
34
  rescue ArchivesSpace::RequestError => e
35
35
  puts e.message
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
4
- require "awesome_print"
5
4
  require "archivesspace/client"
6
5
 
7
6
  username = "admin"
@@ -1,14 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
4
- require "awesome_print"
5
4
  require "archivesspace/client"
6
5
 
7
6
  # official sandbox
8
7
  config = ArchivesSpace::Configuration.new(
9
8
  {
10
- base_uri: "https://sandbox.archivesspace.org/api",
11
- base_repo: "",
9
+ base_uri: "https://sandbox.archivesspace.org/staff/api",
12
10
  username: "admin",
13
11
  password: "admin",
14
12
  page_size: 50,
@@ -19,7 +17,7 @@ config = ArchivesSpace::Configuration.new(
19
17
 
20
18
  client = ArchivesSpace::Client.new(config).login
21
19
 
22
- ap ArchivesSpace::Template.list # view available templates
20
+ puts ArchivesSpace::Template.list # view available templates
23
21
 
24
22
  repo_data = {
25
23
  repo_code: "XYZ",
@@ -40,20 +38,20 @@ begin
40
38
  response = client.post("/repositories/with_agent", repository)
41
39
  if response.result.success?
42
40
  repository = client.repositories.find { |r| r["repo_code"] == "XYZ" }
43
- ap repository
44
- ap client.delete(repository["uri"])
41
+ puts repository
42
+ puts client.delete(repository["uri"])
45
43
  else
46
- ap response.parsed
44
+ puts response.parsed
47
45
  end
48
46
 
49
47
  user = ArchivesSpace::Template.process("user.json.erb", user_data)
50
48
  response = client.post("users", user, {password: user_password})
51
49
  if response.result.success?
52
50
  user = client.users.find { |r| r["username"] == "lmessi" }
53
- ap user
54
- ap client.delete user["uri"]
51
+ puts user
52
+ puts client.delete(user["uri"]).inspect
55
53
  else
56
- ap response.parsed
54
+ puts response.parsed
57
55
  end
58
56
  rescue ArchivesSpace::RequestError => e
59
57
  puts e.message
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
4
- require "awesome_print"
5
4
  require "archivesspace/client"
6
5
 
7
6
  puts ArchivesSpace::Template.list
@@ -1,14 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
4
- require "awesome_print"
5
4
  require "archivesspace/client"
6
5
 
7
6
  # official sandbox
8
7
  config = ArchivesSpace::Configuration.new(
9
8
  {
10
- base_uri: "https://sandbox.archivesspace.org/api",
11
- base_repo: "",
9
+ base_uri: "https://test.archivesspace.org/staff/api",
12
10
  username: "admin",
13
11
  password: "admin",
14
12
  page_size: 50,
@@ -18,4 +16,16 @@ config = ArchivesSpace::Configuration.new(
18
16
  )
19
17
 
20
18
  client = ArchivesSpace::Client.new(config).login
19
+
20
+ # globally scoped
21
21
  puts client.get("version").body
22
+ puts client.get("repositories").body
23
+ puts client.all("users").map { |u| u["username"] }.to_a
24
+
25
+ # repo scoped
26
+ client.repository 2 do
27
+ puts client.get("accessions", query: {page: 1}).parsed["results"].map { |a| a["uri"] }.to_a
28
+ end
29
+
30
+ # globally scoped, full path arg
31
+ puts client.get("repositories/2/resources", query: {all_ids: true}).body
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
4
+ require "archivesspace/client"
5
+
6
+ config = ArchivesSpace::Configuration.new(
7
+ {
8
+ base_uri: "https://test.archivesspace.org/staff/api",
9
+ username: "admin",
10
+ password: "admin",
11
+ page_size: 50,
12
+ throttle: 0,
13
+ verify_ssl: false
14
+ }
15
+ )
16
+
17
+ client = ArchivesSpace::Client.new(config).login
18
+ response = client.get("update-feed")
19
+ last_sequence = response.parsed[0]["sequence"] # get initial sequence value
20
+
21
+ # This is an example only, would also need to handle session/token expiration
22
+ loop do
23
+ puts "Using sequence: #{last_sequence}"
24
+ begin
25
+ response = client.get("update-feed", query: {last_sequence: last_sequence})
26
+ if response.result.success?
27
+ last_sequence = response.parsed.last["sequence"]
28
+ # do something with the response
29
+ puts response.parsed.to_json
30
+ end
31
+ rescue Net::ReadTimeout
32
+ # this is ok if no updates are made within the last 60 seconds
33
+ # (well, as defined by the timeout in client/AppConfig)
34
+ rescue => e
35
+ # some other kind of error occurred
36
+ puts e.message
37
+ break # or handle it in some other way
38
+ end
39
+ end
@@ -1,14 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
4
- require "awesome_print"
5
4
  require "archivesspace/client"
6
5
 
7
6
  # official sandbox
8
7
  config = ArchivesSpace::Configuration.new(
9
8
  {
10
- base_uri: "https://sandbox.archivesspace.org/api",
11
- base_repo: "",
9
+ base_uri: "https://sandbox.archivesspace.org/staff/api",
12
10
  username: "admin",
13
11
  password: "admin",
14
12
  page_size: 50,
@@ -19,26 +17,23 @@ config = ArchivesSpace::Configuration.new(
19
17
 
20
18
  client = ArchivesSpace::Client.new(config).login
21
19
 
22
- user_data = {
20
+ user_data = ArchivesSpace::Template.process("user.json.erb", {
23
21
  username: "bde",
24
22
  name: "BDE",
25
23
  is_admin: false
26
- }
24
+ })
27
25
 
28
- client.post(
29
- "users",
30
- ArchivesSpace::Template.process("user.json.erb", user_data),
31
- {password: "123456"}
32
- )
26
+ client.post("users", user_data, {password: "123456"})
33
27
 
34
28
  users_with_roles = {
35
29
  "bde" => ["repository-basic-data-entry"]
36
30
  }
37
31
 
38
32
  begin
39
- client.config.base_repo = "repositories/2"
40
- results = client.group_user_assignment users_with_roles
41
- ap results.map(&:parsed)
33
+ client.repository 2 do
34
+ results = client.group_user_assignment users_with_roles
35
+ puts results.map(&:parsed)
36
+ end
42
37
  rescue ArchivesSpace::RequestError => e
43
38
  puts e.message
44
39
  end
@@ -4,15 +4,20 @@ module ArchivesSpace
4
4
  class Client
5
5
  include Pagination
6
6
  include Task
7
+
7
8
  attr_accessor :token
8
- attr_reader :config
9
+ attr_reader :config, :context
9
10
 
10
11
  NAME = "ArchivesSpaceClient"
12
+ TOKEN = "X-ArchivesSpace-Session"
11
13
 
12
14
  def initialize(config = Configuration.new)
13
- raise "Invalid configuration object" unless config.is_a? ArchivesSpace::Configuration
15
+ unless config.is_a? ArchivesSpace::Configuration
16
+ raise ConfigurationError, "expected ArchivesSpace::Configuration, got #{config.class}"
17
+ end
14
18
 
15
19
  @config = config
20
+ @context = nil
16
21
  @token = nil
17
22
  end
18
23
 
@@ -38,31 +43,36 @@ module ArchivesSpace
38
43
 
39
44
  # Scoping requests
40
45
  def repository(id)
41
- if id.nil?
42
- use_global_repository
43
- return
44
- end
46
+ return use_global_repository if id.nil?
45
47
 
46
48
  begin
47
49
  Integer(id)
48
- rescue
50
+ rescue ArgumentError, TypeError
49
51
  raise RepositoryIdError, "Invalid Repository id: #{id}"
50
52
  end
51
53
 
52
- @config.base_repo = "repositories/#{id}"
54
+ new_context = "repositories/#{id}"
55
+ return @context = new_context unless block_given?
56
+
57
+ previous = @context
58
+ @context = new_context
59
+ begin
60
+ yield
61
+ ensure
62
+ @context = previous
63
+ end
53
64
  end
54
65
 
55
66
  def use_global_repository
56
- @config.base_repo = ""
67
+ @context = nil
57
68
  end
58
69
 
59
70
  private
60
71
 
61
72
  def request(method, path, options = {})
62
73
  sleep config.throttle
63
- options[:headers] = {"X-ArchivesSpace-Session" => token} if token
64
- result = Request.new(config, method, path, options).execute
65
- Response.new result
74
+ options[:headers] = {TOKEN => token} if token
75
+ Request.new(context, config, method, path, options).execute
66
76
  end
67
77
  end
68
78
  end
@@ -2,27 +2,25 @@
2
2
 
3
3
  module ArchivesSpace
4
4
  class Configuration
5
- def defaults
6
- {
7
- base_uri: "http://localhost:8089",
8
- base_repo: "",
9
- debug: false,
10
- username: "admin",
11
- password: "admin",
12
- page_size: 50,
13
- throttle: 0,
14
- verify_ssl: true,
15
- timeout: 60
16
- }
17
- end
5
+ attr_accessor :base_uri, :debug, :username, :password,
6
+ :page_size, :throttle, :timeout, :verify_ssl
7
+
8
+ DEFAULTS = {
9
+ base_uri: "http://localhost:8089",
10
+ debug: false,
11
+ username: "admin",
12
+ password: "admin",
13
+ page_size: 50,
14
+ throttle: 0,
15
+ timeout: 60,
16
+ verify_ssl: true
17
+ }.freeze
18
18
 
19
19
  def initialize(settings = {})
20
- settings = defaults.merge(settings)
21
- settings.each do |property, value|
22
- next unless defaults.key?(property)
20
+ DEFAULTS.merge(settings).each do |property, value|
21
+ next unless DEFAULTS.key?(property)
23
22
 
24
- instance_variable_set(:"@#{property}", value)
25
- self.class.send(:attr_accessor, property)
23
+ send(:"#{property}=", value)
26
24
  end
27
25
  end
28
26
  end
@@ -33,6 +33,7 @@ module ArchivesSpace
33
33
  loop do
34
34
  options[:query] ||= {}
35
35
  options[:query][:page] = page
36
+ options[:query][:page_size] ||= config.page_size
36
37
  result = get(path, options)
37
38
  results = []
38
39
 
@@ -3,44 +3,32 @@
3
3
  module ArchivesSpace
4
4
  class Request
5
5
  include HTTParty
6
+
6
7
  attr_reader :config, :headers, :method, :path, :options
7
8
 
8
- def default_headers(method = :get)
9
- headers = {
10
- delete: {},
11
- get: {},
12
- post: {
13
- "Content-Type" => "application/json",
14
- "Content-Length" => "nnnn"
15
- },
16
- put: {
17
- "Content-Type" => "application/json",
18
- "Content-Length" => "nnnn"
19
- }
20
- }
21
- headers[method]
22
- end
9
+ DEFAULT_HEADERS = {"Content-Type" => "application/json"}.freeze
23
10
 
24
- def initialize(config, method = "GET", path = "", options = {})
11
+ def initialize(context, config, method = "GET", path = "", options = {})
25
12
  @config = config
13
+
26
14
  @method = method.downcase.to_sym
27
15
  @path = path.gsub(%r{^/+}, "")
16
+
28
17
  @options = options
29
- @options[:headers] =
30
- options[:headers] ? default_headers(@method).merge(options[:headers]) : default_headers(@method)
18
+
19
+ @options[:headers] = DEFAULT_HEADERS.merge(@options.fetch(:headers, {}))
31
20
  @options[:headers]["User-Agent"] = "#{Client::NAME}/#{Client::VERSION}"
21
+
32
22
  @options[:verify] = config.verify_ssl
33
23
  @options[:timeout] = config.timeout
34
24
  @options[:query] = {} unless options.key? :query
35
25
 
36
26
  self.class.debug_output($stdout) if @config.debug
37
-
38
- base_uri = config.base_repo&.length&.positive? ? File.join(config.base_uri, config.base_repo) : config.base_uri
39
- self.class.base_uri base_uri
27
+ self.class.base_uri context ? "#{config.base_uri}/#{context}" : config.base_uri
40
28
  end
41
29
 
42
30
  def execute
43
- self.class.send method, "/#{path}", options
31
+ Response.new(self.class.send(method, "/#{path}", options))
44
32
  end
45
33
  end
46
34
  end
@@ -3,10 +3,6 @@
3
3
  module ArchivesSpace
4
4
  # Perform specific API tasks
5
5
  module Task
6
- # def batch_import(payload, params = {})
7
- # # TODO: create "batch_import", payload, params
8
- # end
9
-
10
6
  def group_user_assignment(users_with_roles)
11
7
  updated = []
12
8
  groups.each do |group|
@@ -29,7 +25,7 @@ module ArchivesSpace
29
25
 
30
26
  next unless update
31
27
 
32
- response = post("/groups/#{uri_to_id(group["uri"])}", group.to_json)
28
+ response = post("/groups/#{uri_to_id(group["uri"])}", group)
33
29
  updated << response
34
30
  end
35
31
  updated
@@ -38,29 +34,29 @@ module ArchivesSpace
38
34
  def login
39
35
  username = config.username
40
36
  password = config.password
41
- base_repo = config.base_repo
42
- use_global_repository # ensure we're in the global scope to login
43
- result = request("POST", "/users/#{username}/login", {query: {password: password}})
44
- unless result.parsed["session"]
45
- raise ConnectionError, "API client login failed as user [#{username}], check username and password are correct"
46
- end
47
37
 
48
- config.base_repo = base_repo # reset repo as set by the cfg
49
- @token = result.parsed["session"]
50
- self
38
+ previous_context = @context
39
+ @context = nil
40
+ begin
41
+ result = request("POST", "/users/#{username}/login", {query: {password: password}})
42
+ unless result.parsed["session"]
43
+ raise AuthenticationError, "Login failed as user [#{username}] (status #{result.status_code}); check username and password"
44
+ end
45
+
46
+ @token = result.parsed["session"]
47
+ self
48
+ ensure
49
+ @context = previous_context
50
+ end
51
51
  end
52
52
 
53
53
  def password_reset(username, password)
54
54
  user = all("users").find { |u| u["username"] == username }
55
- raise RequestError, user.status unless user
55
+ raise RequestError, "User not found: #{username}" unless user
56
56
 
57
- post(user["uri"], user.to_json, {password: password})
57
+ post(user["uri"], user, {password: password})
58
58
  end
59
59
 
60
- # def search(params)
61
- # # TODO: get "search", params
62
- # end
63
-
64
60
  private
65
61
 
66
62
  def uri_to_id(uri)
@@ -7,7 +7,7 @@ module ArchivesSpace
7
7
  end
8
8
 
9
9
  def self.process(template, data)
10
- processor = File.extname(template).delete(".").camelize
10
+ processor = File.extname(template).delete(".").capitalize
11
11
  processor = Object.const_get("ArchivesSpace::Template::#{processor}")
12
12
  processor.new(template, data).process
13
13
  end
@@ -50,7 +50,7 @@ module ArchivesSpace
50
50
  def process
51
51
  t = ERB.new(read_template)
52
52
  r = t.result(binding).squeeze("\n")
53
- JSON.parse(r).to_json
53
+ JSON.parse(r)
54
54
  end
55
55
  end
56
56
 
@@ -60,9 +60,9 @@ module ArchivesSpace
60
60
  end
61
61
 
62
62
  def process
63
- ::Jbuilder.encode do |json|
63
+ ::Jbuilder.new do |json|
64
64
  eval(read_template, binding) # standard:disable Security/Eval
65
- end
65
+ end.attributes!
66
66
  end
67
67
  end
68
68
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ArchivesSpace
4
4
  class Client
5
- VERSION = "0.4.1"
5
+ VERSION = "0.5.0"
6
6
  end
7
7
  end
@@ -3,7 +3,6 @@
3
3
  require "dry/cli"
4
4
  require "httparty"
5
5
  require "json"
6
- require "nokogiri"
7
6
  require "jbuilder"
8
7
 
9
8
  # mixins required first
@@ -23,13 +22,11 @@ require "archivesspace/client/cli/version"
23
22
  require "archivesspace/client/cli" # load the registry last
24
23
 
25
24
  module ArchivesSpace
26
- class ConnectionError < RuntimeError; end
25
+ class AuthenticationError < StandardError; end
27
26
 
28
- class ContextError < RuntimeError; end
27
+ class ConfigurationError < StandardError; end
29
28
 
30
- class RepositoryIdError < RuntimeError; end
29
+ class RepositoryIdError < StandardError; end
31
30
 
32
- class ParamsError < RuntimeError; end
33
-
34
- class RequestError < RuntimeError; end
31
+ class RequestError < StandardError; end
35
32
  end
@@ -11,7 +11,7 @@ describe ArchivesSpace::Client do
11
11
  end
12
12
 
13
13
  it "will raise an error if supplied configuration is of invalid type" do
14
- expect { ArchivesSpace::Client.new({base_uri: CUSTOM_BASE_URI}) }.to raise_error(RuntimeError)
14
+ expect { ArchivesSpace::Client.new({base_uri: CUSTOM_BASE_URI}) }.to raise_error(ArchivesSpace::ConfigurationError)
15
15
  end
16
16
 
17
17
  it "will allow a configuration object to be provided" do
@@ -20,15 +20,86 @@ describe ArchivesSpace::Client do
20
20
  end
21
21
  end
22
22
 
23
+ describe "Login" do
24
+ it "sends the login request at global scope even when a repo context is set" do
25
+ client.repository 2
26
+ expect(ArchivesSpace::Request).to receive(:new)
27
+ .with(nil, client.config, "POST", "/users/admin/login", anything)
28
+ .and_wrap_original do |_orig, *_args|
29
+ double("request", execute: double("response", parsed: {"session" => "token"}, status_code: 200))
30
+ end
31
+ client.login
32
+ end
33
+
34
+ it "restores the previous repo context after login" do
35
+ client.repository 2
36
+ allow(ArchivesSpace::Request).to receive(:new).and_return(
37
+ double("request", execute: double("response", parsed: {"session" => "token"}, status_code: 200))
38
+ )
39
+ client.login
40
+ expect(client.context).to eq "repositories/2"
41
+ end
42
+
43
+ it "raises AuthenticationError and restores context when credentials are rejected" do
44
+ client.repository 2
45
+ allow(ArchivesSpace::Request).to receive(:new).and_return(
46
+ double("request", execute: double("response", parsed: {}, status_code: 403))
47
+ )
48
+ expect { client.login }.to raise_error(ArchivesSpace::AuthenticationError, /status 403/)
49
+ expect(client.context).to eq "repositories/2"
50
+ end
51
+
52
+ it "raises AuthenticationError for a real 403 response (VCR)" do
53
+ bad_client = ArchivesSpace::Client.new(
54
+ ArchivesSpace::Configuration.new(password: "wrong")
55
+ )
56
+ VCR.use_cassette("login_failure") do
57
+ expect { bad_client.login }.to raise_error(
58
+ ArchivesSpace::AuthenticationError, /admin.*status 403/
59
+ )
60
+ end
61
+ end
62
+ end
63
+
64
+ describe "Pagination" do
65
+ it "will have a method for defined paginated record types" do
66
+ ArchivesSpace::Pagination::ENDPOINTS.each do |e|
67
+ next if e.match?("/")
68
+
69
+ expect(client.respond_to?(e.to_sym)).to be true
70
+ end
71
+ end
72
+
73
+ it "will have a method for defined paginated record types with multipart path" do
74
+ expect(client.respond_to?(:people)).to be true
75
+ end
76
+
77
+ it "will pass page_size from configuration to the query" do
78
+ response = double("response", parsed: {"results" => []})
79
+ allow(client).to receive(:get).and_return(response)
80
+ client.all("resources").first
81
+ expect(client).to have_received(:get).with("resources", hash_including(query: hash_including(page_size: 50)))
82
+ end
83
+ end
84
+
85
+ describe "Password reset" do
86
+ it "will raise an error if the user is not found" do
87
+ allow(client).to receive(:all).with("users").and_return([].lazy)
88
+ expect { client.password_reset("nonexistent", "newpass") }.to raise_error(
89
+ ArchivesSpace::RequestError, "User not found: nonexistent"
90
+ )
91
+ end
92
+ end
93
+
23
94
  describe "Repository scoping" do
24
- it "will set the repository with an integer id" do
95
+ it "will set the context with an integer id" do
25
96
  client.repository 2
26
- expect(client.config.base_repo).to eq "repositories/2"
97
+ expect(client.context).to eq "repositories/2"
27
98
  end
28
99
 
29
- it "will set the repository with a string id cast to integer" do
100
+ it "will set the context with a string id cast to integer" do
30
101
  client.repository "2"
31
- expect(client.config.base_repo).to eq "repositories/2"
102
+ expect(client.context).to eq "repositories/2"
32
103
  end
33
104
 
34
105
  it "will fail if the id cannot be cast to integer" do
@@ -37,37 +108,81 @@ describe ArchivesSpace::Client do
37
108
  )
38
109
  end
39
110
 
40
- it "will use the global repo if repository is passed nil" do
111
+ it "will fail if the id is not a valid type" do
112
+ expect { client.repository([]) }.to raise_error(
113
+ ArchivesSpace::RepositoryIdError
114
+ )
115
+ end
116
+
117
+ it "will clear the context when passed nil" do
41
118
  client.repository 2
42
119
  client.repository nil
43
- expect(client.config.base_repo).to eq ""
120
+ expect(client.context).to be_nil
44
121
  end
45
122
 
46
- it "will use the global repo when the method is called" do
123
+ it "will clear the context when use_global_repository is called" do
47
124
  client.repository 2
48
125
  client.use_global_repository
49
- expect(client.config.base_repo).to eq ""
126
+ expect(client.context).to be_nil
127
+ end
128
+
129
+ it "scopes the context to a block and restores afterwards" do
130
+ client.repository(2) do
131
+ expect(client.context).to eq "repositories/2"
132
+ end
133
+ expect(client.context).to be_nil
134
+ end
135
+
136
+ it "restores the previous context when nested" do
137
+ client.repository 2
138
+ client.repository(3) do
139
+ expect(client.context).to eq "repositories/3"
140
+ end
141
+ expect(client.context).to eq "repositories/2"
142
+ end
143
+
144
+ it "restores the context even if the block raises" do
145
+ expect { client.repository(2) { raise "boom" } }.to raise_error("boom")
146
+ expect(client.context).to be_nil
147
+ end
148
+
149
+ it "does not rebrand ArgumentError raised from within the block" do
150
+ expect {
151
+ client.repository(2) { raise ArgumentError, "from caller" }
152
+ }.to raise_error(ArgumentError, "from caller")
50
153
  end
51
154
  end
52
155
 
53
156
  describe "Requests" do
54
157
  it "will have an identifiable user agent" do
55
- request = ArchivesSpace::Request.new(client.config)
158
+ request = ArchivesSpace::Request.new(nil, client.config)
56
159
  expect(request.options[:headers]["User-Agent"]).to eq "#{ArchivesSpace::Client::NAME}/#{ArchivesSpace::Client::VERSION}"
57
160
  end
58
161
  end
59
162
 
60
- describe "Pagination" do
61
- it "will have a method for defined paginated record types" do
62
- ArchivesSpace::Pagination::ENDPOINTS.each do |e|
63
- next if e.match?("/")
163
+ describe "URL construction" do
164
+ let(:config) { ArchivesSpace::Configuration.new(base_uri: "http://localhost:8089") }
64
165
 
65
- expect(client.respond_to?(e.to_sym)).to be true
66
- end
166
+ it "uses the bare base_uri when context is nil" do
167
+ ArchivesSpace::Request.new(nil, config, "GET", "repositories")
168
+ expect(ArchivesSpace::Request.base_uri).to eq "http://localhost:8089"
67
169
  end
68
170
 
69
- it "will have a method for defined paginated record types with multipart path" do
70
- expect(client.respond_to?(:people)).to be true
171
+ it "appends a repository context to the base_uri" do
172
+ ArchivesSpace::Request.new("repositories/2", config, "GET", "resources")
173
+ expect(ArchivesSpace::Request.base_uri).to eq "http://localhost:8089/repositories/2"
174
+ end
175
+
176
+ it "preserves a path prefix in base_uri when context is nil" do
177
+ config.base_uri = "https://example.org/staff/api"
178
+ ArchivesSpace::Request.new(nil, config, "GET", "repositories")
179
+ expect(ArchivesSpace::Request.base_uri).to eq "https://example.org/staff/api"
180
+ end
181
+
182
+ it "preserves a path prefix in base_uri when scoped to a repository" do
183
+ config.base_uri = "https://example.org/staff/api"
184
+ ArchivesSpace::Request.new("repositories/2", config, "GET", "resources")
185
+ expect(ArchivesSpace::Request.base_uri).to eq "https://example.org/staff/api/repositories/2"
71
186
  end
72
187
  end
73
188
 
@@ -21,14 +21,14 @@ describe ArchivesSpace::Template do
21
21
 
22
22
  it "can process an erb template" do
23
23
  data = {repo_code: "ABC", name: "ABC Archive", agent_contact_name: "ABC Admin"}
24
- json = JSON.parse(ArchivesSpace::Template.process("repository_with_agent.json.erb", data))
25
- expect(json["repository"]["repo_code"]).to eq data[:repo_code]
24
+ record = ArchivesSpace::Template.process("repository_with_agent.json.erb", data)
25
+ expect(record["repository"]["repo_code"]).to eq data[:repo_code]
26
26
  end
27
27
 
28
28
  it "can process a jbuilder template" do
29
29
  data = {"title" => "Title", "object_number" => "001.001", "description_level" => "collection"}
30
- json = JSON.parse(ArchivesSpace::Template.process("resource.json.jbuilder", data))
31
- expect(json["id_0"]).to eq data["object_number"]
30
+ record = ArchivesSpace::Template.process("resource.json.jbuilder", data)
31
+ expect(record["id_0"]).to eq data["object_number"]
32
32
  end
33
33
 
34
34
  it "rejects a template that does not match by extension" do
@@ -0,0 +1,37 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: http://localhost:8089/users/admin/login?password=wrong
6
+ body:
7
+ encoding: UTF-8
8
+ string: ''
9
+ headers:
10
+ Content-Type:
11
+ - application/json
12
+ User-Agent:
13
+ - ArchivesSpaceClient/0.3.0
14
+ Accept-Encoding:
15
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
+ Accept:
17
+ - "*/*"
18
+ response:
19
+ status:
20
+ code: 403
21
+ message: Forbidden
22
+ headers:
23
+ Cache-Control:
24
+ - private, must-revalidate, max-age=0
25
+ Content-Type:
26
+ - application/json
27
+ X-Content-Type-Options:
28
+ - nosniff
29
+ Content-Length:
30
+ - '24'
31
+ Server:
32
+ - Jetty(9.4.44.v20210927)
33
+ body:
34
+ encoding: UTF-8
35
+ string: '{"error":"Login failed"}'
36
+ recorded_at: Tue, 22 Apr 2026 12:00:00 GMT
37
+ recorded_with: VCR 6.3.1
data/spec/spec_helper.rb CHANGED
@@ -6,8 +6,8 @@ require "vcr"
6
6
  require "webmock/rspec"
7
7
 
8
8
  # GLOBAL VALUES FOR SPECS
9
- DEFAULT_BASE_URI = "http://localhost:8089"
10
9
  CUSTOM_BASE_URI = "https://archives.university.edu/api"
10
+ DEFAULT_BASE_URI = "http://localhost:8089"
11
11
 
12
12
  VCR.configure do |c|
13
13
  c.cassette_library_dir = "spec/fixtures/cassettes"
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: archivesspace-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Cooper
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-04-19 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: aruba
@@ -76,72 +75,72 @@ dependencies:
76
75
  name: rspec
77
76
  requirement: !ruby/object:Gem::Requirement
78
77
  requirements:
79
- - - '='
78
+ - - "~>"
80
79
  - !ruby/object:Gem::Version
81
- version: 3.6.0
80
+ version: '3.13'
82
81
  type: :development
83
82
  prerelease: false
84
83
  version_requirements: !ruby/object:Gem::Requirement
85
84
  requirements:
86
- - - '='
85
+ - - "~>"
87
86
  - !ruby/object:Gem::Version
88
- version: 3.6.0
87
+ version: '3.13'
89
88
  - !ruby/object:Gem::Dependency
90
89
  name: rubocop
91
90
  requirement: !ruby/object:Gem::Requirement
92
91
  requirements:
93
- - - '='
92
+ - - "~>"
94
93
  - !ruby/object:Gem::Version
95
- version: '1.56'
94
+ version: '1.72'
96
95
  type: :development
97
96
  prerelease: false
98
97
  version_requirements: !ruby/object:Gem::Requirement
99
98
  requirements:
100
- - - '='
99
+ - - "~>"
101
100
  - !ruby/object:Gem::Version
102
- version: '1.56'
101
+ version: '1.72'
103
102
  - !ruby/object:Gem::Dependency
104
103
  name: standard
105
104
  requirement: !ruby/object:Gem::Requirement
106
105
  requirements:
107
- - - '='
106
+ - - "~>"
108
107
  - !ruby/object:Gem::Version
109
- version: 1.31.0
108
+ version: '1.44'
110
109
  type: :development
111
110
  prerelease: false
112
111
  version_requirements: !ruby/object:Gem::Requirement
113
112
  requirements:
114
- - - '='
113
+ - - "~>"
115
114
  - !ruby/object:Gem::Version
116
- version: 1.31.0
115
+ version: '1.44'
117
116
  - !ruby/object:Gem::Dependency
118
117
  name: vcr
119
118
  requirement: !ruby/object:Gem::Requirement
120
119
  requirements:
121
- - - '='
120
+ - - "~>"
122
121
  - !ruby/object:Gem::Version
123
- version: 6.2.0
122
+ version: '6.3'
124
123
  type: :development
125
124
  prerelease: false
126
125
  version_requirements: !ruby/object:Gem::Requirement
127
126
  requirements:
128
- - - '='
127
+ - - "~>"
129
128
  - !ruby/object:Gem::Version
130
- version: 6.2.0
129
+ version: '6.3'
131
130
  - !ruby/object:Gem::Dependency
132
131
  name: webmock
133
132
  requirement: !ruby/object:Gem::Requirement
134
133
  requirements:
135
- - - '='
134
+ - - "~>"
136
135
  - !ruby/object:Gem::Version
137
- version: 3.19.1
136
+ version: '3.24'
138
137
  type: :development
139
138
  prerelease: false
140
139
  version_requirements: !ruby/object:Gem::Requirement
141
140
  requirements:
142
- - - '='
141
+ - - "~>"
143
142
  - !ruby/object:Gem::Version
144
- version: 3.19.1
143
+ version: '3.24'
145
144
  - !ruby/object:Gem::Dependency
146
145
  name: dry-cli
147
146
  requirement: !ruby/object:Gem::Requirement
@@ -184,34 +183,20 @@ dependencies:
184
183
  - - "~>"
185
184
  - !ruby/object:Gem::Version
186
185
  version: '2.0'
187
- - !ruby/object:Gem::Dependency
188
- name: nokogiri
189
- requirement: !ruby/object:Gem::Requirement
190
- requirements:
191
- - - "~>"
192
- - !ruby/object:Gem::Version
193
- version: '1.10'
194
- type: :runtime
195
- prerelease: false
196
- version_requirements: !ruby/object:Gem::Requirement
197
- requirements:
198
- - - "~>"
199
- - !ruby/object:Gem::Version
200
- version: '1.10'
201
186
  - !ruby/object:Gem::Dependency
202
187
  name: jbuilder
203
188
  requirement: !ruby/object:Gem::Requirement
204
189
  requirements:
205
190
  - - "~>"
206
191
  - !ruby/object:Gem::Version
207
- version: 2.11.5
192
+ version: '2.12'
208
193
  type: :runtime
209
194
  prerelease: false
210
195
  version_requirements: !ruby/object:Gem::Requirement
211
196
  requirements:
212
197
  - - "~>"
213
198
  - !ruby/object:Gem::Version
214
- version: 2.11.5
199
+ version: '2.12'
215
200
  description: Interact with ArchivesSpace via the API.
216
201
  email:
217
202
  - mark.c.cooper@outlook.com
@@ -237,6 +222,7 @@ files:
237
222
  - examples/repo_and_user.rb
238
223
  - examples/templates.rb
239
224
  - examples/test_connection.rb
225
+ - examples/update_feed.rb
240
226
  - examples/user_groups.rb
241
227
  - exe/asclient
242
228
  - features/exec.feature
@@ -263,12 +249,12 @@ files:
263
249
  - spec/archivesspace/configuration_spec.rb
264
250
  - spec/archivesspace/templates_spec.rb
265
251
  - spec/fixtures/cassettes/backend_version.yml
252
+ - spec/fixtures/cassettes/login_failure.yml
266
253
  - spec/spec_helper.rb
267
254
  homepage: ''
268
255
  licenses:
269
256
  - MIT
270
257
  metadata: {}
271
- post_install_message:
272
258
  rdoc_options: []
273
259
  require_paths:
274
260
  - lib
@@ -283,8 +269,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
283
269
  - !ruby/object:Gem::Version
284
270
  version: '0'
285
271
  requirements: []
286
- rubygems_version: 3.5.9
287
- signing_key:
272
+ rubygems_version: 4.0.10
288
273
  specification_version: 4
289
274
  summary: Interact with ArchivesSpace via the API.
290
275
  test_files: []