collectionspace-client 0.15.0 → 1.0.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: d797561c0b44c79ce0bda224d05ff05de6fa7c932b2c33d4a9c888116c6d6fbb
4
- data.tar.gz: bfbd46caa314f5fc6620b468e14e262983f3f52a444622ef55669c60ad5c4f84
3
+ metadata.gz: e8efeeecb56c776b3a9b04c57e412e22a3ee1fc091f1c400a38412d14eb2bfc4
4
+ data.tar.gz: 6cadb420c9cf8dd23794be7bdd069641fd6738afad9faaedfa8a45fa42ca9cf8
5
5
  SHA512:
6
- metadata.gz: 697f5207854022997a0acf1e2249113c763447a5597677d4b7f7b157244467a2c0bee0d163d152ee2191950e41c9478a21443f967087c87e85a765c137542865
7
- data.tar.gz: 71d59341de8048599691df601042915c803c10c6710982c76eeda366684aab1ba27ce694a285bcf349d9de08faba78d4951838114ff96059f24c417dc6b9f1a8
6
+ metadata.gz: afa91f5b105bef4a7d8507f703081fc0a18e342defac0b4b11e9809334070f301722813053e574a435b2d2bca3fb86ef3e98e53b2b70041bb1cee9209928922b
7
+ data.tar.gz: e023f885dd4912e71f2df99b59dd339578c75278654b22b23213ba888826b06f63ba2487114ffa0386dbe442b247183933f82e70c7d58ae3b64eea8dc44d6837
@@ -7,7 +7,7 @@ jobs:
7
7
  runs-on: ubuntu-latest
8
8
  strategy:
9
9
  matrix:
10
- ruby-version: ['3.2', '3.1', '3.0']
10
+ ruby-version: ['3.3', '3.2', '3.1', '3.0']
11
11
  steps:
12
12
  - name: Checkout code
13
13
  uses: actions/checkout@v3
@@ -18,7 +18,6 @@ jobs:
18
18
  uses: ruby/setup-ruby@v1
19
19
  with:
20
20
  bundler-cache: true
21
- ruby-version: 2.7
22
21
  rubygems: latest
23
22
 
24
23
  - name: Release Gem
data/.gitignore CHANGED
@@ -5,7 +5,6 @@
5
5
  /.bundle/
6
6
  /.vscode
7
7
  /.yardoc
8
- /Gemfile.lock
9
8
  /_yardoc/
10
9
  /coverage/
11
10
  /doc/
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.2.1
1
+ 3.0.6
data/.standard.yml ADDED
@@ -0,0 +1 @@
1
+ ruby_version: 3.0
data/Gemfile.lock ADDED
@@ -0,0 +1,126 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ collectionspace-client (1.0.0)
5
+ httparty
6
+ json
7
+ nokogiri
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ addressable (2.8.7)
13
+ public_suffix (>= 2.0.2, < 7.0)
14
+ ast (2.4.2)
15
+ awesome_print (1.9.2)
16
+ base64 (0.2.0)
17
+ bigdecimal (3.1.9)
18
+ coderay (1.1.3)
19
+ crack (1.0.0)
20
+ bigdecimal
21
+ rexml
22
+ csv (3.3.2)
23
+ diff-lcs (1.5.1)
24
+ docile (1.4.1)
25
+ hashdiff (1.1.2)
26
+ httparty (0.22.0)
27
+ csv
28
+ mini_mime (>= 1.0.0)
29
+ multi_xml (>= 0.5.2)
30
+ json (2.9.1)
31
+ language_server-protocol (3.17.0.3)
32
+ lint_roller (1.1.0)
33
+ method_source (1.1.0)
34
+ mini_mime (1.1.5)
35
+ mini_portile2 (2.8.8)
36
+ multi_xml (0.6.0)
37
+ nokogiri (1.17.2)
38
+ mini_portile2 (~> 2.8.2)
39
+ racc (~> 1.4)
40
+ parallel (1.26.3)
41
+ parser (3.3.7.0)
42
+ ast (~> 2.4.1)
43
+ racc
44
+ pry (0.15.2)
45
+ coderay (~> 1.1)
46
+ method_source (~> 1.0)
47
+ public_suffix (6.0.1)
48
+ racc (1.8.1)
49
+ rainbow (3.1.1)
50
+ rake (13.2.1)
51
+ regexp_parser (2.10.0)
52
+ rexml (3.4.0)
53
+ rspec (3.13.0)
54
+ rspec-core (~> 3.13.0)
55
+ rspec-expectations (~> 3.13.0)
56
+ rspec-mocks (~> 3.13.0)
57
+ rspec-core (3.13.2)
58
+ rspec-support (~> 3.13.0)
59
+ rspec-expectations (3.13.3)
60
+ diff-lcs (>= 1.2.0, < 2.0)
61
+ rspec-support (~> 3.13.0)
62
+ rspec-mocks (3.13.2)
63
+ diff-lcs (>= 1.2.0, < 2.0)
64
+ rspec-support (~> 3.13.0)
65
+ rspec-support (3.13.2)
66
+ rubocop (1.70.0)
67
+ json (~> 2.3)
68
+ language_server-protocol (>= 3.17.0)
69
+ parallel (~> 1.10)
70
+ parser (>= 3.3.0.2)
71
+ rainbow (>= 2.2.2, < 4.0)
72
+ regexp_parser (>= 2.9.3, < 3.0)
73
+ rubocop-ast (>= 1.36.2, < 2.0)
74
+ ruby-progressbar (~> 1.7)
75
+ unicode-display_width (>= 2.4.0, < 4.0)
76
+ rubocop-ast (1.37.0)
77
+ parser (>= 3.3.1.0)
78
+ rubocop-performance (1.23.1)
79
+ rubocop (>= 1.48.1, < 2.0)
80
+ rubocop-ast (>= 1.31.1, < 2.0)
81
+ ruby-progressbar (1.13.0)
82
+ simplecov (0.22.0)
83
+ docile (~> 1.1)
84
+ simplecov-html (~> 0.11)
85
+ simplecov_json_formatter (~> 0.1)
86
+ simplecov-html (0.13.1)
87
+ simplecov_json_formatter (0.1.4)
88
+ standard (1.44.0)
89
+ language_server-protocol (~> 3.17.0.2)
90
+ lint_roller (~> 1.0)
91
+ rubocop (~> 1.70.0)
92
+ standard-custom (~> 1.0.0)
93
+ standard-performance (~> 1.6)
94
+ standard-custom (1.0.2)
95
+ lint_roller (~> 1.0)
96
+ rubocop (~> 1.50)
97
+ standard-performance (1.6.0)
98
+ lint_roller (~> 1.1)
99
+ rubocop-performance (~> 1.23.0)
100
+ unicode-display_width (3.1.4)
101
+ unicode-emoji (~> 4.0, >= 4.0.4)
102
+ unicode-emoji (4.0.4)
103
+ vcr (6.3.1)
104
+ base64
105
+ webmock (3.24.0)
106
+ addressable (>= 2.8.0)
107
+ crack (>= 0.3.2)
108
+ hashdiff (>= 0.4.0, < 2.0.0)
109
+
110
+ PLATFORMS
111
+ ruby
112
+
113
+ DEPENDENCIES
114
+ awesome_print
115
+ bundler
116
+ collectionspace-client!
117
+ pry
118
+ rake
119
+ rspec
120
+ simplecov
121
+ standard
122
+ vcr
123
+ webmock
124
+
125
+ BUNDLED WITH
126
+ 2.4.1
data/README.md CHANGED
@@ -37,10 +37,11 @@ bundle exec rake
37
37
  ```bash
38
38
  gem install gem-release
39
39
  # https://github.com/svenfuchs/gem-release#gem-bump
40
- gem bump --version $VERSION --tag
40
+ gem bump --version $VERSION
41
41
  # i.e.
42
42
  gem bump --version minor --pretend # dryrun
43
43
  gem bump --version minor # do it for real
44
+ bundle # update gem version in Gemfile.lock
44
45
  # PR and merge will publish new version
45
46
  ```
46
47
 
data/bin/standardrb ADDED
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'standardrb' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
12
+
13
+ bundle_binstub = File.expand_path("bundle", __dir__)
14
+
15
+ if File.file?(bundle_binstub)
16
+ if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
17
+ load(bundle_binstub)
18
+ else
19
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
20
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
21
+ end
22
+ end
23
+
24
+ require "rubygems"
25
+ require "bundler/setup"
26
+
27
+ load Gem.bin_path("standard", "standardrb")
@@ -9,8 +9,10 @@ Gem::Specification.new do |spec|
9
9
  spec.email = ["mark.cooper@lyrasis.org"]
10
10
 
11
11
  spec.summary = "CollectionSpace API client."
12
+ spec.description = "Client for interacting with CollectionSpace Services API"
12
13
  spec.homepage = "https://github.com/lyrasis/collectionspace-client.git"
13
14
  spec.license = "MIT"
15
+ spec.required_ruby_version = ">= 3.0.6"
14
16
 
15
17
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
18
  spec.bindir = "exe"
@@ -24,11 +26,10 @@ Gem::Specification.new do |spec|
24
26
  spec.add_development_dependency "awesome_print"
25
27
  spec.add_development_dependency "bundler"
26
28
  spec.add_development_dependency "pry"
27
- spec.add_development_dependency "rake", "~> 13.0"
29
+ spec.add_development_dependency "rake"
28
30
  spec.add_development_dependency "rspec"
29
- spec.add_development_dependency "rubocop"
30
- spec.add_development_dependency "simplecov", "~> 0.21"
31
+ spec.add_development_dependency "simplecov"
31
32
  spec.add_development_dependency "standard"
32
- spec.add_development_dependency "vcr", "~> 6.1"
33
+ spec.add_development_dependency "vcr"
33
34
  spec.add_development_dependency "webmock"
34
35
  end
data/examples/demo.rb CHANGED
@@ -4,13 +4,33 @@ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
4
4
  require "awesome_print"
5
5
  require "collectionspace/client"
6
6
 
7
- client = CollectionSpace::Client.new(
8
- CollectionSpace::Configuration.new(
9
- base_uri: "https://core.dev.collectionspace.org/cspace-services",
10
- username: "admin@core.collectionspace.org",
11
- password: "Administrator"
12
- )
7
+ config = CollectionSpace::Configuration.new(
8
+ base_uri: "https://core.collectionspace.org/cspace-services",
9
+ username: "admin@core.collectionspace.org",
10
+ password: "Administrator"
13
11
  )
12
+ client = CollectionSpace::Client.new(config)
13
+
14
+ version_data = client.version
15
+ puts "Success getting UI version?: #{version_data.ui.success?}"
16
+ puts "Instance UI profile: #{version_data.ui.profile}"
17
+ puts "Instance UI version: #{version_data.ui.version}"
18
+ puts "Combined UI profile/version: #{version_data.ui.joined}"
19
+ puts ""
20
+ puts "Success getting API version?: #{version_data.api.success?}"
21
+ puts "API major version number: #{version_data.api.major}"
22
+ puts "API display version: #{version_data.api.joined}"
23
+ puts ""
24
+ puts "Client version: #{version_data.client}"
25
+
26
+ # GET REQUEST FOR CONDITIONCHECK RECORDS AND PRINT THE PARSED RESPONSE AND XML
27
+ response = client.get("conditionchecks")
28
+ ap response.parsed if response.result.success?
29
+
30
+ # GET ALL PERSON RECORDS AND PROCESS PER PAGE (INSTEAD OF WAITING FOR ALL)
31
+ client.all("personauthorities/urn:cspace:name(person)/items").each do |item|
32
+ puts item
33
+ end
14
34
 
15
35
  # GET REQUEST FOR CONDITIONCHECK RECORDS AND PRINT THE PARSED RESPONSE AND XML
16
36
  response = client.get("conditionchecks")
data/examples/reports.rb CHANGED
@@ -1,45 +1,22 @@
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 "collectionspace/client"
6
5
 
7
- STANDARD_TENANTS = [
8
- :anthro,
9
- :bonsai,
10
- :botgarden,
11
- :core,
12
- :fcart,
13
- :herbarium,
14
- :lhmc,
15
- :materials,
16
- :publicart
17
- ]
18
-
19
- # https://github.com/collectionspace/Tools/blob/master/scripts/install_report_records.sh
20
- # https://github.com/collectionspace/Tools/blob/master/scripts/create-report-records.sh
21
-
22
- STANDARD_REPORTS = CollectionSpace::Report.all
23
-
24
- STANDARD_TENANTS.each do |tenant|
25
- client = CollectionSpace::Client.new(
26
- CollectionSpace::Configuration.new(
27
- base_uri: "https://#{tenant}.dev.collectionspace.org/cspace-services",
28
- username: "admin@#{tenant}.collectionspace.org",
29
- password: "Administrator"
30
- )
6
+ client = CollectionSpace::Client.new(
7
+ CollectionSpace::Configuration.new(
8
+ base_uri: "https://core.dev.collectionspace.org/cspace-services",
9
+ username: "admin@core.collectionspace.org",
10
+ password: "Administrator"
31
11
  )
32
- base = client.config.base_uri
33
- .delete_suffix("/cspace-services")
34
- .delete_prefix("https://")
12
+ )
13
+
14
+ report_xml = File.join("spec", "fixtures", "files", "Exhibition_List_Basic.xml")
35
15
 
36
- STANDARD_REPORTS.each do |report|
37
- response = client.add_report(report)
38
- if response.result.success?
39
- puts "Added #{report[:name]} to #{base}"
40
- else
41
- puts "FAILED TO ADD #{report[:name]} to #{base}"
42
- puts response.inspect
43
- end
44
- end
16
+ response = client.add_report(report_xml)
17
+ if response.result.success?
18
+ puts "Report added/updated"
19
+ else
20
+ puts "Report addition/update failed"
21
+ puts response.inspect
45
22
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CollectionSpace
4
+ ApiVersion = Struct.new(:status, :message, :major, :minor, :patch,
5
+ :build, keyword_init: true) do
6
+ def success? = status == :success
7
+
8
+ def failure? = !success?
9
+
10
+ def joined
11
+ return if failure?
12
+
13
+ [major, minor].compact.join(".")
14
+ end
15
+ end
16
+ end
@@ -14,6 +14,21 @@ module CollectionSpace
14
14
  @config = config
15
15
  end
16
16
 
17
+ # User is required to be authenticated in order to access accounts
18
+ # endpoint. We cannot distinguish between unknown user and known
19
+ # user with bad password because CollectionSpace returns a 401
20
+ # error regardless of reason for
21
+ # non-authentication/authorization
22
+ def can_authenticate?
23
+ return false unless login_credentials_provided?
24
+
25
+ response = get("accounts/0/accountperms")
26
+ response.result.success? &&
27
+ response.parsed.respond_to?(:dig) &&
28
+ response.parsed.dig("account_permission", "account",
29
+ "userId") == config.username
30
+ end
31
+
17
32
  def get(path, options = {})
18
33
  request "GET", path, options
19
34
  end
@@ -43,8 +58,21 @@ module CollectionSpace
43
58
  request "DELETE", path
44
59
  end
45
60
 
61
+ def version
62
+ Struct.new(:api, :client, :ui, keyword_init: true)
63
+ .new(
64
+ api: get_api_version,
65
+ client: VERSION,
66
+ ui: CollectionSpace::UiVersion.call(self)
67
+ )
68
+ end
69
+
46
70
  private
47
71
 
72
+ def login_credentials_provided?
73
+ config.username && config.password
74
+ end
75
+
48
76
  def check_payload(payload)
49
77
  errors = Nokogiri::XML(payload).errors
50
78
  raise CollectionSpace::PayloadError, errors if errors.any?
@@ -54,5 +82,23 @@ module CollectionSpace
54
82
  sleep config.throttle
55
83
  Response.new(Request.new(config, method, path, options).execute)
56
84
  end
85
+
86
+ def get_api_version
87
+ response = get("systeminfo")
88
+ unless response.result.success?
89
+ return CollectionSpace::ApiVersion.new(
90
+ status: :failure, message: response.result.body
91
+ )
92
+ end
93
+
94
+ version_info = response.parsed.dig("system_info_common", "version")
95
+ CollectionSpace::ApiVersion.new(
96
+ status: :success,
97
+ major: version_info["major"],
98
+ minor: version_info["minor"],
99
+ patch: version_info["patch"],
100
+ build: version_info["build"]
101
+ )
102
+ end
57
103
  end
58
104
  end
@@ -21,7 +21,7 @@ module CollectionSpace
21
21
  settings.each do |property, value|
22
22
  next unless DEFAULTS.key?(property)
23
23
 
24
- instance_variable_set("@#{property}", value)
24
+ instance_variable_set(:"@#{property}", value)
25
25
  end
26
26
  end
27
27
  end
@@ -18,10 +18,11 @@ module CollectionSpace
18
18
  end
19
19
 
20
20
  # add / update reports
21
- def add_report(data = {}, params = {pgSz: 100})
22
- payload = Template.process("report", data)
21
+ def add_report(payload_path, params = {pgSz: 100})
22
+ payload = File.read(File.expand_path(payload_path))
23
+ report_name = payload.match(/<name>(.*)<\/name>/)[1]
23
24
  response = get("reports", {query: params})
24
- create_or_update(response, "reports", "name", data[:name], payload)
25
+ create_or_update(response, "reports", "name", report_name, payload)
25
26
  end
26
27
 
27
28
  # returns Array of authority doctypes for use in setting up batches
@@ -81,7 +82,7 @@ module CollectionSpace
81
82
  path: service[:path],
82
83
  namespace: "#{service[:ns_prefix]}_#{schema}",
83
84
  field: field,
84
- expression: "#{operator} '#{value.gsub(/'/, "\\\\'")}'"
85
+ expression: "#{operator} '#{value.gsub("'", "\\\\'")}'"
85
86
  )
86
87
  search(search_args, sortBy: CollectionSpace::Search::DEFAULT_SORT)
87
88
  end
@@ -109,16 +110,13 @@ module CollectionSpace
109
110
  }.fetch(path, %w[abstract_common_list list_item])
110
111
  end
111
112
 
112
- def reindex_full_text(doctype, csids = [])
113
- if csids.any?
114
- run_job(
115
- "Reindex Full Text", :reindex_full_text, :reindex_by_csids, {doctype: doctype, csids: csids}
116
- )
117
- else
118
- run_job(
119
- "Reindex Full Text", :reindex_full_text, :reindex_by_doctype, {doctype: doctype}
120
- )
121
- end
113
+ def reindex_full_text(doctype = nil, csids = [])
114
+ run_job(
115
+ "Reindex Full Text",
116
+ :reindex_full_text,
117
+ :reindex,
118
+ {doctype: doctype, csids: csids}
119
+ )
122
120
  end
123
121
 
124
122
  # @param id [String] media record's identificationNumber value
@@ -16,7 +16,7 @@ module CollectionSpace
16
16
 
17
17
  def from_hash(query)
18
18
  query.each do |property, value|
19
- instance_variable_set("@#{property}", value)
19
+ instance_variable_set(:"@#{property}", value)
20
20
  end
21
21
  self
22
22
  end
@@ -12,6 +12,12 @@ module CollectionSpace
12
12
  path: "acquisitions",
13
13
  term: nil
14
14
  },
15
+ "chronologyauthorities" => {
16
+ identifier: "shortIdentifier",
17
+ ns_prefix: "chronologies",
18
+ path: "chronologyauthorities/urn:cspace:name(#{subtype})/items",
19
+ term: "chronology#{TERM_SUFFIX}"
20
+ },
15
21
  "citationauthorities" => {
16
22
  identifier: "shortIdentifier",
17
23
  ns_prefix: "citations",
@@ -48,18 +54,48 @@ module CollectionSpace
48
54
  path: "conservation",
49
55
  term: nil
50
56
  },
57
+ "consultations" => {
58
+ identifier: "consultationNumber",
59
+ ns_prefix: "consultations",
60
+ path: "consultations",
61
+ term: nil
62
+ },
63
+ "deaccessions" => {
64
+ identifier: "deaccessionNumber",
65
+ ns_prefix: "deaccessions",
66
+ path: "deaccessions",
67
+ term: nil
68
+ },
69
+ "dutiesofcare" => {
70
+ identifier: "dutyOfCareNumber",
71
+ ns_prefix: "dutiesofcare",
72
+ path: "dutiesofcare",
73
+ term: nil
74
+ },
51
75
  "exhibitions" => {
52
76
  identifier: "exhibitionNumber",
53
77
  ns_prefix: "exhibitions",
54
78
  path: "exhibitions",
55
79
  term: nil
56
80
  },
81
+ "exits" => {
82
+ identifier: "exitNumber",
83
+ ns_prefix: "exits",
84
+ path: "exits",
85
+ term: nil
86
+ },
57
87
  "groups" => {
58
88
  identifier: "title",
59
89
  ns_prefix: "groups",
60
90
  path: "groups",
61
91
  term: nil
62
92
  },
93
+ "heldintrusts" => {
94
+ identifier: "heldInTrustNumber",
95
+ ns_prefix: "heldintrusts",
96
+ path: "heldintrusts",
97
+ term: nil
98
+ },
63
99
  "insurances" => {
64
100
  identifier: "insuranceIndemnityReferenceNumber",
65
101
  ns_prefix: "insurances",
@@ -114,6 +150,12 @@ module CollectionSpace
114
150
  path: "movements",
115
151
  term: nil
116
152
  },
153
+ "nagprainventories" => {
154
+ identifier: "inventoryNumber",
155
+ ns_prefix: "nagprainventories",
156
+ path: "nagprainventories",
157
+ term: nil
158
+ },
117
159
  "objectexit" => {
118
160
  identifier: "exitNumber",
119
161
  ns_prefix: "objectexit",
@@ -162,6 +204,24 @@ module CollectionSpace
162
204
  path: "relations",
163
205
  term: nil
164
206
  },
207
+ "repatriationrequests" => {
208
+ identifier: "requestNumber",
209
+ ns_prefix: "repatriationrequests",
210
+ path: "repatriationrequests",
211
+ term: nil
212
+ },
213
+ "restrictedmedia" => {
214
+ identifier: "identificationNumber",
215
+ ns_prefix: "restrictedmedia",
216
+ path: "restrictedmedia",
217
+ term: nil
218
+ },
219
+ "summarydocumentations" => {
220
+ identifier: "documentationNumber",
221
+ ns_prefix: "summarydocumentations",
222
+ path: "summarydocumentations",
223
+ term: nil
224
+ },
165
225
  "taxonomyauthority" => {
166
226
  identifier: "shortIdentifier",
167
227
  ns_prefix: "taxon",
@@ -1,10 +1,16 @@
1
1
  <?xml version="1.0" encoding="utf-8" standalone="yes"?>
2
2
  <ns2:invocationContext xmlns:ns2="http://collectionspace.org/services/common/invocable">
3
+ <% if data[:csids].any? %>
3
4
  <mode>list</mode>
4
- <docType><%= data[:doctype] %></docType>
5
5
  <listCSIDs>
6
- <% data[:csids].each do |csid| %>
7
- <csid><%= csid %></csid>
8
- <% end %>
6
+ <% data[:csids].each do |csid| %>
7
+ <csid><%= csid %></csid>
8
+ <% end %>
9
9
  </listCSIDs>
10
+ <% else %>
11
+ <mode>nocontext</mode>
12
+ <% end %>
13
+ <% if data[:doctype] %>
14
+ <docType><%= data[:doctype] %></docType>
15
+ <% end %>
10
16
  </ns2:invocationContext>
@@ -11,11 +11,8 @@
11
11
  <createsNewFocus>false</createsNewFocus>
12
12
  <forDocTypes>
13
13
  <forDocType>Acquisition</forDocType>
14
- <forDocType>Batch</forDocType>
15
- <forDocType>Blob</forDocType>
16
14
  <forDocType>Citation</forDocType>
17
15
  <forDocType>Citationauthority</forDocType>
18
- <forDocType>Claim</forDocType>
19
16
  <forDocType>CollectionObject</forDocType>
20
17
  <forDocType>Conceptauthority</forDocType>
21
18
  <forDocType>Conceptitem</forDocType>
@@ -32,7 +29,6 @@
32
29
  <forDocType>ObjectExit</forDocType>
33
30
  <forDocType>Organization</forDocType>
34
31
  <forDocType>Orgauthority</forDocType>
35
- <forDocType>Osteology</forDocType>
36
32
  <forDocType>Person</forDocType>
37
33
  <forDocType>Personauthority</forDocType>
38
34
  <forDocType>Placeauthority</forDocType>
@@ -45,7 +41,6 @@
45
41
  <forDocType>Vocabulary</forDocType>
46
42
  <forDocType>Vocabularyitem</forDocType>
47
43
  <forDocType>Workauthority</forDocType>
48
- <forDocType>Workitem</forDocType>
49
44
  </forDocTypes>
50
45
  </ns2:batch_common>
51
46
  </document>
@@ -0,0 +1,170 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "strscan"
4
+ require "net/http"
5
+ require "uri"
6
+
7
+ module CollectionSpace
8
+ # CollectionSpace request
9
+ class UiVersion
10
+ Data = Struct.new(:status, :message, :profile, :version,
11
+ keyword_init: true) do
12
+ def success? = status == :success
13
+
14
+ def failure? = !success?
15
+
16
+ def joined
17
+ return if failure?
18
+
19
+ [profile, version].compact.join(" ")
20
+ end
21
+ end
22
+
23
+ class << self
24
+ def call(...) = new(...).call
25
+ end
26
+
27
+ # @param client [CollectionSpace::Client]
28
+ def initialize(client)
29
+ @uri = client.config.base_uri
30
+ end
31
+
32
+ def call
33
+ body = retrieve_response
34
+ return body if body.respond_to?(:status) && body.status == :failure
35
+
36
+ script = last_script_src(body)
37
+ return script if script.respond_to?(:status) && script.status == :failure
38
+
39
+ version = extract_version(script) if script
40
+ return version if version.respond_to?(:status) &&
41
+ version.status == :failure
42
+
43
+ profile = extract_profile(script) if version
44
+ return profile if profile.respond_to?(:status) &&
45
+ profile.status == :failure
46
+
47
+ Data.new(status: :success,
48
+ profile: profile.downcase.tr(" ", "-"),
49
+ version: version)
50
+ end
51
+
52
+ private
53
+
54
+ attr_reader :uri
55
+
56
+ def retrieve_response
57
+ unless response.is_a?(Net::HTTPSuccess)
58
+ return Data.new(status: :failure, message: response.message)
59
+ end
60
+
61
+ response.body
62
+ end
63
+
64
+ def response
65
+ @response ||= fetch(base_uri)
66
+ rescue => err
67
+ err
68
+ end
69
+
70
+ def base_uri = URI(uri.sub(/\/cspace-services\/?/, ""))
71
+
72
+ def fetch(uri, limit = 10)
73
+ uri = URI(uri) unless uri.is_a?(URI)
74
+
75
+ # You should choose a better exception.
76
+ raise ArgumentError, "too many HTTP redirects" if limit == 0
77
+
78
+ response = Net::HTTP.get_response(uri)
79
+
80
+ case response
81
+ when Net::HTTPSuccess
82
+ response
83
+ when Net::HTTPRedirection
84
+ location = response["location"]
85
+ new_loc = "#{base_uri}#{location}"
86
+ fetch(new_loc, limit - 1)
87
+ else
88
+ response.value
89
+ end
90
+ end
91
+
92
+ def last_script_src(str)
93
+ scripts = []
94
+ scanner = StringScanner.new(str)
95
+ script_begin = Regexp.new("<script src=\"")
96
+ script_end_str = '"></script>'
97
+ script_end = Regexp.new(script_end_str)
98
+
99
+ while scanner.exist?(script_begin)
100
+ scanner.scan_until(script_begin)
101
+ scripts << scanner.scan_until(script_end)
102
+ .delete_suffix(script_end_str)
103
+ end
104
+
105
+ if scripts.empty?
106
+ return Data.new(status: :failure,
107
+ message: "No CollectionSpace UI plugin script sources " \
108
+ "detected for #{base_uri}")
109
+ end
110
+
111
+ scripts.last
112
+ end
113
+
114
+ def extract_version(src)
115
+ case src
116
+ when /^\/cspace-ui/
117
+ extract_from_cspace_ui_src(src)
118
+ when /cspace-ui-plugin-profile-.*@\d.*cspaceUIPluginProfile.*\.min\.js/
119
+ get_specific_delivered_version(src)
120
+ when /^https:\/\/cdn\.jsdelivr\.net\/npm.*@latest/
121
+ get_latest_npm_version(src)
122
+ else
123
+ Data.new(status: :failure, message: "Unhandled src type: #{src}")
124
+ end
125
+ end
126
+
127
+ def extract_from_cspace_ui_src(src)
128
+ src.match(/@(.*)\.min\.js/)
129
+ .captures
130
+ .first
131
+ rescue
132
+ Value.new(status: :failure, message: "Cannot extract version from #{src}")
133
+ end
134
+
135
+ def get_specific_delivered_version(src)
136
+ src.match(/cspace-ui-plugin-profile-.*@(\d[^\/]+)\//)
137
+ .captures
138
+ .first
139
+ end
140
+
141
+ def get_latest_npm_version(src)
142
+ package = src.match(/npm\/(.*)@latest/)
143
+ .captures.first
144
+ uri = URI("https://data.jsdelivr.com/v1/packages/npm/#{package}")
145
+ response = fetch(uri)
146
+ unless response.is_a?(Net::HTTPSuccess)
147
+ return Data.new(status: :failure,
148
+ message: "ERROR: Cannot retrieve latest version " \
149
+ "number for #{package} from jsdelivr: " \
150
+ "#{response.message}")
151
+ end
152
+
153
+ data = JSON.parse(response.body)
154
+ value = data.dig("tags", "latest")
155
+ unless value
156
+ return Data.new(status: :failure,
157
+ message: "Could not extract latest version from #{uri}")
158
+ end
159
+
160
+ value
161
+ end
162
+
163
+ def extract_profile(src)
164
+ return "core" if src.match?(/^\/cspace-ui\/cspaceUI@/)
165
+
166
+ src.match(/UIPluginProfile([^@]+)(?:@|\.min\.js)/)
167
+ .captures.first
168
+ end
169
+ end
170
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module CollectionSpace
4
4
  class Client
5
- VERSION = "0.15.0"
5
+ VERSION = "1.0.0"
6
6
  end
7
7
  end
@@ -8,15 +8,16 @@ require "uri"
8
8
  require "collectionspace/client/helpers"
9
9
  require "collectionspace/client/template"
10
10
 
11
+ require "collectionspace/client/api_version"
11
12
  require "collectionspace/client/batch"
12
13
  require "collectionspace/client/client"
13
14
  require "collectionspace/client/configuration"
14
15
  require "collectionspace/client/refname"
15
- require "collectionspace/client/report"
16
16
  require "collectionspace/client/request"
17
17
  require "collectionspace/client/response"
18
18
  require "collectionspace/client/search"
19
19
  require "collectionspace/client/service"
20
+ require "collectionspace/client/ui_version"
20
21
  require "collectionspace/client/version"
21
22
 
22
23
  module CollectionSpace
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: collectionspace-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Cooper
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-03-08 00:00:00.000000000 Z
11
+ date: 2025-05-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -96,20 +96,6 @@ dependencies:
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rake
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: '13.0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: '13.0'
111
- - !ruby/object:Gem::Dependency
112
- name: rspec
113
99
  requirement: !ruby/object:Gem::Requirement
114
100
  requirements:
115
101
  - - ">="
@@ -123,7 +109,7 @@ dependencies:
123
109
  - !ruby/object:Gem::Version
124
110
  version: '0'
125
111
  - !ruby/object:Gem::Dependency
126
- name: rubocop
112
+ name: rspec
127
113
  requirement: !ruby/object:Gem::Requirement
128
114
  requirements:
129
115
  - - ">="
@@ -140,16 +126,16 @@ dependencies:
140
126
  name: simplecov
141
127
  requirement: !ruby/object:Gem::Requirement
142
128
  requirements:
143
- - - "~>"
129
+ - - ">="
144
130
  - !ruby/object:Gem::Version
145
- version: '0.21'
131
+ version: '0'
146
132
  type: :development
147
133
  prerelease: false
148
134
  version_requirements: !ruby/object:Gem::Requirement
149
135
  requirements:
150
- - - "~>"
136
+ - - ">="
151
137
  - !ruby/object:Gem::Version
152
- version: '0.21'
138
+ version: '0'
153
139
  - !ruby/object:Gem::Dependency
154
140
  name: standard
155
141
  requirement: !ruby/object:Gem::Requirement
@@ -168,16 +154,16 @@ dependencies:
168
154
  name: vcr
169
155
  requirement: !ruby/object:Gem::Requirement
170
156
  requirements:
171
- - - "~>"
157
+ - - ">="
172
158
  - !ruby/object:Gem::Version
173
- version: '6.1'
159
+ version: '0'
174
160
  type: :development
175
161
  prerelease: false
176
162
  version_requirements: !ruby/object:Gem::Requirement
177
163
  requirements:
178
- - - "~>"
164
+ - - ">="
179
165
  - !ruby/object:Gem::Version
180
- version: '6.1'
166
+ version: '0'
181
167
  - !ruby/object:Gem::Dependency
182
168
  name: webmock
183
169
  requirement: !ruby/object:Gem::Requirement
@@ -192,7 +178,7 @@ dependencies:
192
178
  - - ">="
193
179
  - !ruby/object:Gem::Version
194
180
  version: '0'
195
- description:
181
+ description: Client for interacting with CollectionSpace Services API
196
182
  email:
197
183
  - mark.cooper@lyrasis.org
198
184
  executables: []
@@ -204,15 +190,17 @@ files:
204
190
  - ".github/workflows/publish.yml"
205
191
  - ".gitignore"
206
192
  - ".rspec"
207
- - ".rubocop.yml"
208
193
  - ".ruby-version"
194
+ - ".standard.yml"
209
195
  - ".travis.yml"
210
196
  - Gemfile
197
+ - Gemfile.lock
211
198
  - LICENSE.txt
212
199
  - README.md
213
200
  - Rakefile
214
201
  - bin/console
215
202
  - bin/rspec
203
+ - bin/standardrb
216
204
  - collectionspace-client.gemspec
217
205
  - examples/batches.rb
218
206
  - examples/demo.rb
@@ -223,29 +211,29 @@ files:
223
211
  - examples/search.rb
224
212
  - examples/update_password.rb
225
213
  - lib/collectionspace/client.rb
214
+ - lib/collectionspace/client/api_version.rb
226
215
  - lib/collectionspace/client/batch.rb
227
216
  - lib/collectionspace/client/client.rb
228
217
  - lib/collectionspace/client/configuration.rb
229
218
  - lib/collectionspace/client/helpers.rb
230
219
  - lib/collectionspace/client/refname.rb
231
- - lib/collectionspace/client/report.rb
232
220
  - lib/collectionspace/client/request.rb
233
221
  - lib/collectionspace/client/response.rb
234
222
  - lib/collectionspace/client/search.rb
235
223
  - lib/collectionspace/client/service.rb
236
224
  - lib/collectionspace/client/template.rb
237
225
  - lib/collectionspace/client/templates/batch.xml.erb
238
- - lib/collectionspace/client/templates/reindex_by_csids.xml.erb
239
- - lib/collectionspace/client/templates/reindex_by_doctype.xml.erb
226
+ - lib/collectionspace/client/templates/reindex.xml.erb
240
227
  - lib/collectionspace/client/templates/reindex_full_text.xml.erb
241
228
  - lib/collectionspace/client/templates/report.xml.erb
242
229
  - lib/collectionspace/client/templates/reset_media_blob.xml.erb
230
+ - lib/collectionspace/client/ui_version.rb
243
231
  - lib/collectionspace/client/version.rb
244
232
  homepage: https://github.com/lyrasis/collectionspace-client.git
245
233
  licenses:
246
234
  - MIT
247
235
  metadata: {}
248
- post_install_message:
236
+ post_install_message:
249
237
  rdoc_options: []
250
238
  require_paths:
251
239
  - lib
@@ -253,15 +241,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
253
241
  requirements:
254
242
  - - ">="
255
243
  - !ruby/object:Gem::Version
256
- version: '0'
244
+ version: 3.0.6
257
245
  required_rubygems_version: !ruby/object:Gem::Requirement
258
246
  requirements:
259
247
  - - ">="
260
248
  - !ruby/object:Gem::Version
261
249
  version: '0'
262
250
  requirements: []
263
- rubygems_version: 3.4.7
264
- signing_key:
251
+ rubygems_version: 3.5.23
252
+ signing_key:
265
253
  specification_version: 4
266
254
  summary: CollectionSpace API client.
267
255
  test_files: []
data/.rubocop.yml DELETED
@@ -1,4 +0,0 @@
1
- require: standard
2
-
3
- inherit_gem:
4
- standard: config/base.yml
@@ -1,180 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module CollectionSpace
4
- # CollectionSpace report
5
- class Report
6
- def self.all
7
- [
8
- {
9
- name: "Acquisition Summary",
10
- notes: "An acquisition summary report. Runs on a single record only.",
11
- doctype: "Acquisition",
12
- supports_single_doc: "true",
13
- supports_doc_list: "false",
14
- supports_group: "false",
15
- supports_no_context: "false",
16
- filename: "acq_basic.jrxml",
17
- mimetype: "application/pdf"
18
- },
19
- {
20
- name: "Acquisition Basic List",
21
- notes: "Catalog info for objects related to an acquisition record. Runs on a single record only.",
22
- doctype: "Acquisition",
23
- supports_single_doc: "true",
24
- supports_doc_list: "false",
25
- supports_group: "false",
26
- supports_no_context: "false",
27
- filename: "Acq_List_Basic.jrxml",
28
- mimetype: "application/pdf"
29
- },
30
- {
31
- name: "Condition Check Basic List",
32
- notes: "Catalog info for objects related to a condition check record. Runs on a single record only.",
33
- doctype: "Conditioncheck",
34
- supports_single_doc: "true",
35
- supports_doc_list: "false",
36
- supports_group: "false",
37
- supports_no_context: "false",
38
- filename: "CC_List_Basic.jrxml",
39
- mimetype: "application/pdf"
40
- },
41
- {
42
- name: "Exhibition Basic List",
43
- notes: "Catalog info for objects related to a exhibition record. Runs on a single record only.",
44
- doctype: "Exhibition",
45
- supports_single_doc: "true",
46
- supports_doc_list: "false",
47
- supports_group: "false",
48
- supports_no_context: "false",
49
- filename: "Exhibition_List_Basic.jrxml",
50
- mimetype: "application/pdf"
51
- },
52
- {
53
- name: "Group Basic List",
54
- notes: "Catalog info for objects related to a group record. Runs on a single record only.",
55
- doctype: "Group",
56
- supports_single_doc: "true",
57
- supports_doc_list: "false",
58
- supports_group: "false",
59
- supports_no_context: "false",
60
- filename: "Group_List_Basic.jrxml",
61
- mimetype: "application/pdf"
62
- },
63
- {
64
- name: "Loan In Basic List",
65
- notes: "Catalog info for objects related to a loan in record. Runs on a single record only.",
66
- doctype: "Loanin",
67
- supports_single_doc: "true",
68
- supports_doc_list: "false",
69
- supports_group: "false",
70
- supports_no_context: "false",
71
- filename: "LoansIn_List_Basic.jrxml",
72
- mimetype: "application/pdf"
73
- },
74
- {
75
- name: "Loan Out Basic List",
76
- notes: "Catalog info for objects related to a loan out record. Runs on a single record only.",
77
- doctype: "Loanout",
78
- supports_single_doc: "true",
79
- supports_doc_list: "false",
80
- supports_group: "false",
81
- supports_no_context: "false",
82
- filename: "LoansOut_List_Basic.jrxml",
83
- mimetype: "application/pdf"
84
- },
85
- {
86
- name: "Acquisition Ethnographic Object List",
87
- notes: "Core acquisition report. Runs on a single record only.",
88
- doctype: "Acquisition",
89
- supports_single_doc: "true",
90
- supports_doc_list: "false",
91
- supports_group: "false",
92
- supports_no_context: "false",
93
- filename: "coreAcquisition.jrxml",
94
- mimetype: "application/pdf"
95
- },
96
- {
97
- name: "Group Object Ethnographic Object List",
98
- notes: "Core group object report. Runs on a single record only.",
99
- doctype: "Group",
100
- supports_single_doc: "true",
101
- supports_doc_list: "false",
102
- supports_group: "false",
103
- supports_no_context: "false",
104
- filename: "coreGroupObject.jrxml",
105
- mimetype: "application/pdf"
106
- },
107
- {
108
- name: "Intake Ethnographic Object List",
109
- notes: "Core intake report. Runs on a single record only.",
110
- doctype: "Intake",
111
- supports_single_doc: "true",
112
- supports_doc_list: "false",
113
- supports_group: "false",
114
- supports_no_context: "false",
115
- filename: "coreIntake.jrxml",
116
- mimetype: "application/pdf"
117
- },
118
- {
119
- name: "Loan In Ethnographic Object List",
120
- notes: "Core loan in report. Runs on a single record only.",
121
- doctype: "Loanin",
122
- supports_single_doc: "true",
123
- supports_doc_list: "false",
124
- supports_group: "false",
125
- supports_no_context: "false",
126
- filename: "coreLoanIn.jrxml",
127
- mimetype: "application/pdf"
128
- },
129
- {
130
- name: "Loan Out Ethnographic Object List",
131
- notes: "Core loan out report. Runs on a single record only.",
132
- doctype: "Loanout",
133
- supports_single_doc: "true",
134
- supports_doc_list: "false",
135
- supports_group: "false",
136
- supports_no_context: "false",
137
- filename: "coreLoanOut.jrxml",
138
- mimetype: "application/pdf"
139
- },
140
- {
141
- name: "Object Exit Ethnographic Object List",
142
- notes: "Core object exit report. Runs on a single record only.",
143
- doctype: "ObjectExit",
144
- supports_single_doc: "true",
145
- supports_doc_list: "false",
146
- supports_group: "false",
147
- supports_no_context: "false",
148
- filename: "coreObjectExit.jrxml",
149
- mimetype: "application/pdf"
150
- },
151
- {
152
- name: "Object Valuation",
153
- notes: "Returns latest valuation information for selected objects",
154
- doctype: "CollectionObject",
155
- supports_single_doc: "false",
156
- supports_doc_list: "true",
157
- supports_group: "false",
158
- supports_no_context: "true",
159
- filename: "object_valuation.jrxml",
160
- mimetype: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
161
- },
162
- {
163
- name: "Systematic Inventory",
164
- notes: "Generate a checklist for performing an inventory on a range of storage locations. Runs on all records, using the provided start and end locations.",
165
- doctype: "Locationitem",
166
- supports_single_doc: "false",
167
- supports_doc_list: "false",
168
- supports_group: "false",
169
- supports_no_context: "true",
170
- filename: "systematicInventory.jrxml",
171
- mimetype: "application/pdf"
172
- }
173
- ]
174
- end
175
-
176
- def self.find(key, value)
177
- all.find { |report| report[key] == value }
178
- end
179
- end
180
- end
@@ -1,5 +0,0 @@
1
- <?xml version="1.0" encoding="utf-8" standalone="yes"?>
2
- <ns2:invocationContext xmlns:ns2="http://collectionspace.org/services/common/invocable">
3
- <mode>nocontext</mode>
4
- <docType><%= data[:doctype] %></docType>
5
- </ns2:invocationContext>