dor-services-client 0.4.0 → 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: d0938b1979de1f6767e88044a77182623502a0ee923d445fd11d892f83c9c81c
4
- data.tar.gz: d091617c14b075d111980b1052ab0662382362bbbdd2ffe943609c4d94f997ee
3
+ metadata.gz: cbe8578f95f4533b0b91fe9a3c47ede0d1ba51db157e5f015928ba7b5b1fe19e
4
+ data.tar.gz: b3e4e136c27186b625b86ebc138d59f032e03f1f6c908f65ee6c7206c73c7143
5
5
  SHA512:
6
- metadata.gz: 121eecbb6172914d1bd345167ae7f92064c815c17634f2e017cf1c39617368da597e4d0cb9598c7d907cff64e3d7740d4916f174ba3d1c33b5b2e57b7eb66087
7
- data.tar.gz: 99ce5863977ec58b8b315ed91867eeb8c1f2f31efe763f045ca0519676d0b03842bdf9095f67bee5e9ea5bd041c3ddf939c26dd792d68f645eabd591594e4b67
6
+ metadata.gz: 933595fee0dbdec82b6d46c5b1bb63ed0cf4022d702ae97df1c294a8688d14e080fc893303ea981def0f9d8d86d08afff16517811a1e26fbd611258023259025
7
+ data.tar.gz: fd88271153d2c461cedacfb7447c22fc4c47b87db50c5d44b8484a9f63fdb56ebc285006605ee5280a43688aa4461dae8cf3cb72f0d29dffec496e7a33531e76
@@ -24,6 +24,7 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.add_dependency 'activesupport', '>= 4.2', '< 6'
26
26
  spec.add_dependency 'faraday', '~> 0.15'
27
+ spec.add_dependency 'nokogiri', '~> 1.8'
27
28
 
28
29
  spec.add_development_dependency 'bundler', '~> 1.17'
29
30
  spec.add_development_dependency 'rake', '~> 10.0'
@@ -4,6 +4,7 @@ require 'dor/services/client/version'
4
4
  require 'singleton'
5
5
  require 'faraday'
6
6
  require 'active_support/core_ext/hash/indifferent_access'
7
+ require 'active_support/core_ext/module/delegation'
7
8
  require 'dor/services/client/versioned_service'
8
9
  require 'dor/services/client/files'
9
10
  require 'dor/services/client/objects'
@@ -16,6 +17,13 @@ module Dor
16
17
  class Client
17
18
  class Error < StandardError; end
18
19
 
20
+ # Error that is raised when the remote server returns some unexpected response
21
+ # this could be any 4xx or 5xx status.
22
+ class UnexpectedResponse < Error; end
23
+
24
+ # Error that is raised when the remote server returns some unparsable response
25
+ class MalformedResponse < Error; end
26
+
19
27
  DEFAULT_VERSION = 'v1'
20
28
 
21
29
  include Singleton
@@ -40,68 +48,85 @@ module Dor
40
48
  @release_tags ||= ReleaseTags.new(connection: connection, version: DEFAULT_VERSION)
41
49
  end
42
50
 
43
- def self.configure(url:, username: nil, password: nil)
44
- instance.url = url
45
- instance.username = username
46
- instance.password = password
47
- # Force connection to be re-established when `.configure` is called
48
- instance.connection = nil
49
- end
51
+ class << self
52
+ def configure(url:, username: nil, password: nil)
53
+ instance.url = url
54
+ instance.username = username
55
+ instance.password = password
56
+ # Force connection to be re-established when `.configure` is called
57
+ instance.connection = nil
58
+ end
50
59
 
51
- # Creates a new object in DOR
52
- # @return [HashWithIndifferentAccess] the response, which includes a :pid
53
- def self.register(params:)
54
- instance.objects.register(params: params)
55
- end
60
+ delegate :objects, :files, :workflow, :workspace, :release_tags, to: :instance
61
+ private :objects, :files, :workflow, :workspace, :release_tags
56
62
 
57
- # @param [String] object the identifier for the object
58
- # @param [String] filename the name of the file to retrieve
59
- # @return [String] the file contents from the workspace
60
- def self.retrieve_file(object:, filename:)
61
- instance.files.retrieve(object: object, filename: filename)
62
- end
63
+ # Creates a new object in DOR
64
+ # @return [HashWithIndifferentAccess] the response, which includes a :pid
65
+ delegate :register, to: :objects
63
66
 
64
- # @param [String] object the identifier for the object
65
- # @return [Array<String>] the list of filenames in the workspace
66
- def self.list_files(object:)
67
- instance.files.list(object: object)
68
- end
67
+ # @param [String] object the identifier for the object
68
+ # @param [String] filename the name of the file to retrieve
69
+ # @return [String] the file contents from the workspace
70
+ def retrieve_file(object:, filename:)
71
+ files.retrieve(object: object, filename: filename)
72
+ end
69
73
 
70
- # Initializes a new workflow
71
- # @param object [String] the pid for the object
72
- # @param wf_name [String] the name of the workflow
73
- # @raises [Error] if the request is unsuccessful.
74
- # @return nil
75
- def self.initialize_workflow(object:, wf_name:)
76
- instance.workflow.create(object: object, wf_name: wf_name)
77
- end
74
+ # Get the preserved file contents
75
+ # @param [String] object the identifier for the object
76
+ # @param [String] filename the name of the file to retrieve
77
+ # @param [Integer] version the version of the file to retrieve
78
+ # @return [String] the file contents from the SDR
79
+ delegate :preserved_content, to: :files
80
+
81
+ # @param [String] object the identifier for the object
82
+ # @return [Array<String>] the list of filenames in the workspace
83
+ def list_files(object:)
84
+ files.list(object: object)
85
+ end
78
86
 
79
- # Initializes a new workspace
80
- # @param object [String] the pid for the object
81
- # @param source [String] the path to the object
82
- # @raises [Error] if the request is unsuccessful.
83
- # @return nil
84
- def self.initialize_workspace(object:, source:)
85
- instance.workspace.create(object: object, source: source)
86
- end
87
+ # Initializes a new workflow
88
+ # @param object [String] the pid for the object
89
+ # @param wf_name [String] the name of the workflow
90
+ # @raises [UnexpectedResponse] if the request is unsuccessful.
91
+ # @return nil
92
+ def initialize_workflow(object:, wf_name:)
93
+ workflow.create(object: object, wf_name: wf_name)
94
+ end
87
95
 
88
- # Creates a new release tag for the object
89
- # @param object [String] the pid for the object
90
- # @param release [Boolean]
91
- # @param what [String]
92
- # @param to [String]
93
- # @param who [String]
94
- # @return [Boolean] true if successful
95
- def self.create_release_tag(object:, release:, what:, to:, who:)
96
- instance.release_tags.create(object: object, release: release, what: what, to: to, who: who)
96
+ # Initializes a new workspace
97
+ # @param object [String] the pid for the object
98
+ # @param source [String] the path to the object
99
+ # @raises [UnexpectedResponse] if the request is unsuccessful.
100
+ # @return nil
101
+ def initialize_workspace(object:, source:)
102
+ workspace.create(object: object, source: source)
103
+ end
104
+
105
+ # Creates a new release tag for the object
106
+ # @param object [String] the pid for the object
107
+ # @param release [Boolean]
108
+ # @param what [String]
109
+ # @param to [String]
110
+ # @param who [String]
111
+ # @return [Boolean] true if successful
112
+ def create_release_tag(object:, release:, what:, to:, who:)
113
+ release_tags.create(object: object, release: release, what: what, to: to, who: who)
114
+ end
115
+
116
+ # Publish a new object
117
+ # @param object [String] the pid for the object
118
+ # @raise [UnexpectedResponse] when the response is not successful.
119
+ # @return [boolean] true on success
120
+ delegate :publish, to: :objects
97
121
  end
98
122
 
99
- # Publish a new object
123
+ # Gets the current version number for the object
100
124
  # @param object [String] the pid for the object
101
- # @raise [Error] when the response is not successful.
102
- # @return [boolean] true on success
103
- def self.publish(object:)
104
- instance.objects.publish(object: object)
125
+ # @raise [UnexpectedResponse] when the response is not successful.
126
+ # @raise [MalformedResponse] when the response is not parseable.
127
+ # @return [Integer] the current version
128
+ def self.current_version(object:)
129
+ instance.objects.current_version(object: object)
105
130
  end
106
131
 
107
132
  attr_writer :url, :username, :password, :connection
@@ -5,18 +5,39 @@ module Dor
5
5
  class Client
6
6
  # API calls relating to files
7
7
  class Files < VersionedService
8
+ # Get the contents from the workspace
9
+ # @param [String] object the identifier for the object
10
+ # @param [String] filename the name of the file to retrieve
11
+ # @return [String] the file contents from the workspace
8
12
  def retrieve(object:, filename:)
9
13
  resp = connection.get do |req|
10
- req.url "#{version}/objects/#{object}/contents/#{filename}"
14
+ req.url "#{api_version}/objects/#{object}/contents/#{filename}"
11
15
  end
12
16
  return unless resp.success?
13
17
 
14
18
  resp.body
15
19
  end
16
20
 
21
+ # Get the preserved file contents
22
+ # @param [String] object the identifier for the object
23
+ # @param [String] filename the name of the file to retrieve
24
+ # @param [Integer] version the version of the file to retrieve
25
+ # @return [String] the file contents from the SDR
26
+ def preserved_content(object:, filename:, version:)
27
+ resp = connection.get do |req|
28
+ req.url "#{api_version}/sdr/objects/#{object}/content/#{CGI.escape(filename)}?version=#{version}"
29
+ end
30
+ return unless resp.success?
31
+
32
+ resp.body
33
+ end
34
+
35
+ # Get the list of files in the workspace
36
+ # @param [String] object the identifier for the object
37
+ # @return [Array<String>] the list of filenames in the workspace
17
38
  def list(object:)
18
39
  resp = connection.get do |req|
19
- req.url "#{version}/objects/#{object}/contents"
40
+ req.url "#{api_version}/objects/#{object}/contents"
20
41
  end
21
42
  return [] unless resp.success?
22
43
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'nokogiri'
4
+
3
5
  module Dor
4
6
  module Services
5
7
  class Client
@@ -8,29 +10,72 @@ module Dor
8
10
  # Creates a new object in DOR
9
11
  # @return [HashWithIndifferentAccess] the response, which includes a :pid
10
12
  def register(params:)
13
+ json = register_response(params: params)
14
+ JSON.parse(json).with_indifferent_access
15
+ end
16
+
17
+ # Publish a new object
18
+ # @param object [String] the pid for the object
19
+ # @raise [UnexpectedResponse] when the response is not successful.
20
+ # @return [boolean] true on success
21
+ def publish(object:)
11
22
  resp = connection.post do |req|
12
- req.url "#{version}/objects"
23
+ req.url "#{api_version}/objects/#{object}/publish"
24
+ end
25
+ raise UnexpectedResponse, "#{resp.reason_phrase}: #{resp.status} (#{resp.body})" unless resp.success?
26
+
27
+ true
28
+ end
29
+
30
+ # Gets the current version number for the object
31
+ # @param object [String] the pid for the object
32
+ # @raise [UnexpectedResponse] when the response is not successful.
33
+ # @raise [MalformedResponse] when the response is not parseable.
34
+ # @return [Integer] the current version
35
+ def current_version(object:)
36
+ xml = current_version_response(object: object)
37
+ begin
38
+ doc = Nokogiri::XML xml
39
+ raise if doc.root.name != 'currentVersion'
40
+
41
+ return Integer(doc.text)
42
+ rescue StandardError
43
+ raise MalformedResponse, "Unable to parse XML from current_version API call: #{xml}"
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ # make the registration request to the server
50
+ # @raises [UnexpectedResponse] on an unsuccessful response from the server
51
+ # @returns [String] the raw JSON from the server
52
+ def register_response(params:)
53
+ resp = connection.post do |req|
54
+ req.url "#{api_version}/objects"
13
55
  req.headers['Content-Type'] = 'application/json'
14
56
  # asking the service to return JSON (else it'll be plain text)
15
57
  req.headers['Accept'] = 'application/json'
16
58
  req.body = params.to_json
17
59
  end
18
- raise Error, "#{resp.reason_phrase}: #{resp.status} (#{resp.body})" unless resp.success?
60
+ return resp.body if resp.success?
19
61
 
20
- JSON.parse(resp.body).with_indifferent_access
62
+ raise UnexpectedResponse, "#{resp.reason_phrase}: #{resp.status} (#{resp.body})"
21
63
  end
22
64
 
23
- # Publish a new object
24
- # @param object [String] the pid for the object
25
- # @raise [Error] when the response is not successful.
26
- # @return [boolean] true on success
27
- def publish(object:)
28
- resp = connection.post do |req|
29
- req.url "#{version}/objects/#{object}/publish"
65
+ # make the request to the server for the currentVersion xml
66
+ # @raises [UnexpectedResponse] on an unsuccessful response from the server
67
+ # @returns [String] the raw xml from the server
68
+ def current_version_response(object:)
69
+ resp = connection.get do |req|
70
+ req.url current_version_path(object: object)
30
71
  end
31
- raise Error, "#{resp.reason_phrase}: #{resp.status} (#{resp.body})" unless resp.success?
72
+ return resp.body if resp.success?
32
73
 
33
- true
74
+ raise UnexpectedResponse, "#{resp.reason_phrase}: #{resp.status} (#{resp.body}) for #{object}"
75
+ end
76
+
77
+ def current_version_path(object:)
78
+ "#{api_version}/sdr/objects/#{object}/current_version"
34
79
  end
35
80
  end
36
81
  end
@@ -11,6 +11,7 @@ module Dor
11
11
  # @param what [String]
12
12
  # @param to [String]
13
13
  # @param who [String]
14
+ # @raises [UnexpectedResponse] if the request is unsuccessful.
14
15
  # @return [Boolean] true if successful
15
16
  # rubocop:disable Metrics/MethodLength
16
17
  def create(object:, release:, what:, to:, who:)
@@ -21,11 +22,11 @@ module Dor
21
22
  release: release
22
23
  }
23
24
  resp = connection.post do |req|
24
- req.url "#{version}/objects/#{object}/release_tags"
25
+ req.url "#{api_version}/objects/#{object}/release_tags"
25
26
  req.headers['Content-Type'] = 'application/json'
26
27
  req.body = params.to_json
27
28
  end
28
- raise Error, "#{resp.reason_phrase}: #{resp.status} (#{resp.body})" unless resp.success?
29
+ raise UnexpectedResponse, "#{resp.reason_phrase}: #{resp.status} (#{resp.body})" unless resp.success?
29
30
 
30
31
  true
31
32
  end
@@ -3,7 +3,7 @@
3
3
  module Dor
4
4
  module Services
5
5
  class Client
6
- VERSION = '0.4.0'
6
+ VERSION = '0.5.0'
7
7
  end
8
8
  end
9
9
  end
@@ -7,12 +7,12 @@ module Dor
7
7
  class VersionedService
8
8
  def initialize(connection:, version:)
9
9
  @connection = connection
10
- @version = version
10
+ @api_version = version
11
11
  end
12
12
 
13
13
  private
14
14
 
15
- attr_reader :connection, :version
15
+ attr_reader :connection, :api_version
16
16
  end
17
17
  end
18
18
  end
@@ -8,13 +8,13 @@ module Dor
8
8
  # Begin a new workflow
9
9
  # @param object [String] the pid for the object
10
10
  # @param wf_name [String] the name of the workflow
11
- # @raises [Error] if the request is unsuccessful.
11
+ # @raises [UnexpectedResponse] if the request is unsuccessful.
12
12
  # @return nil
13
13
  def create(object:, wf_name:)
14
14
  resp = connection.post do |req|
15
- req.url "#{version}/objects/#{object}/apo_workflows/#{wf_name}"
15
+ req.url "#{api_version}/objects/#{object}/apo_workflows/#{wf_name}"
16
16
  end
17
- raise Error, "#{resp.reason_phrase}: #{resp.status} (#{resp.body})" unless resp.success?
17
+ raise UnexpectedResponse, "#{resp.reason_phrase}: #{resp.status} (#{resp.body})" unless resp.success?
18
18
  end
19
19
  end
20
20
  end
@@ -4,18 +4,18 @@ module Dor
4
4
  module Services
5
5
  class Client
6
6
  # API calls that are about the DOR workspace
7
- class Workspace < VersionedService
7
+ class Workspace < VersionedService
8
8
  # Initializes a new workspace
9
9
  # @param object [String] the pid for the object
10
10
  # @param source [String] the path to the object
11
- # @raises [Error] if the request is unsuccessful.
11
+ # @raises [UnexpectedResponse] if the request is unsuccessful.
12
12
  # @return nil
13
13
  def create(object:, source:)
14
14
  resp = connection.post do |req|
15
- req.url "#{version}/objects/#{object}/initialize_workspace"
15
+ req.url "#{api_version}/objects/#{object}/initialize_workspace"
16
16
  req.params['source'] = source
17
17
  end
18
- raise Error, "#{resp.reason_phrase}: #{resp.status} (#{resp.body})" unless resp.success?
18
+ raise UnexpectedResponse, "#{resp.reason_phrase}: #{resp.status} (#{resp.body})" unless resp.success?
19
19
  end
20
20
  end
21
21
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dor-services-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Coyne
@@ -45,6 +45,20 @@ dependencies:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0.15'
48
+ - !ruby/object:Gem::Dependency
49
+ name: nokogiri
50
+ requirement: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.8'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.8'
48
62
  - !ruby/object:Gem::Dependency
49
63
  name: bundler
50
64
  requirement: !ruby/object:Gem::Requirement