sdr-client 0.2.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3a995f725226eef2f793d8b0b45e487c37a6e34899b223a1f2c6864f32204325
4
+ data.tar.gz: dd947253f76fe8dcfd20565537e89fa86c4b6b13a4e6c68b2ecf285d30406c08
5
+ SHA512:
6
+ metadata.gz: f3f0c8d2c9994c4a0408438199105dfdcccb0901e4905220cbf99fd69b3d5e9a735752c3de638264c1397986985ecb2a9f992ab1f1fad2e3245025e78eed1dd0
7
+ data.tar.gz: 300591272660ad09e74bc992742c3c26c14251bd107252b441a2e2856ed981749dfd5ff298704b13c360a0b3dab0cc89fceb2282a9f301fe24909eaac0b8de0d
@@ -0,0 +1,5 @@
1
+ ## Why was this change made?
2
+
3
+
4
+
5
+ ## Was the documentation (README, wiki) updated?
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /.DS_Store
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
13
+
14
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,15 @@
1
+
2
+ inherit_from: .rubocop_todo.yml
3
+
4
+ AllCops:
5
+ TargetRubyVersion: 2.6
6
+ Exclude:
7
+ - 'bin/console'
8
+ - 'vendor/**/*'
9
+
10
+ Layout/LineLength:
11
+ Max: 120
12
+
13
+ Metrics/BlockLength:
14
+ Exclude:
15
+ - 'spec/**/*'
@@ -0,0 +1,21 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2020-01-10 17:16:01 -0600 using RuboCop version 0.79.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 1
10
+ Metrics/AbcSize:
11
+ Max: 16
12
+
13
+ # Offense count: 1
14
+ # Configuration parameters: CountComments, ExcludedMethods.
15
+ Metrics/MethodLength:
16
+ Max: 13
17
+
18
+ # Offense count: 2
19
+ # Configuration parameters: CountKeywordArgs.
20
+ Metrics/ParameterLists:
21
+ Max: 8
@@ -0,0 +1,20 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.6.4
7
+ before_install: gem install bundler -v 2.1.2
8
+
9
+ before_script:
10
+ - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
11
+ - chmod +x ./cc-test-reporter
12
+ - ./cc-test-reporter before-build
13
+ after_script:
14
+ - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
15
+
16
+ env:
17
+ global:
18
+ - CC_TEST_REPORTER_ID=859fcfe88b00c026d15dce30e838e2299face8088b49fe62bc3a02d1507ce3d5
19
+ notifications:
20
+ email: false
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in sdr-client.gemspec
6
+ gemspec
7
+
8
+ gem 'byebug'
data/LICENSE ADDED
@@ -0,0 +1,14 @@
1
+ Copyright (c) 2020 by The Board of Trustees of the Leland Stanford
2
+ Junior University. All rights reserved.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License"); you
5
+ may not use this file except in compliance with the License. You
6
+ may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13
+ implied. See the License for the specific language governing
14
+ permissions and limitations under the License.
@@ -0,0 +1,25 @@
1
+ [![Build Status](https://travis-ci.org/sul-dlss/sdr-client.svg?branch=master)](https://travis-ci.org/sul-dlss/sdr-client)
2
+ [![Maintainability](https://api.codeclimate.com/v1/badges/1210855d46d4f424bf30/maintainability)](https://codeclimate.com/github/sul-dlss/sdr-client/maintainability)
3
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/1210855d46d4f424bf30/test_coverage)](https://codeclimate.com/github/sul-dlss/sdr-client/test_coverage)
4
+ [![Gem Version](https://badge.fury.io/rb/sdr-client.svg)](https://badge.fury.io/rb/sdr-client)
5
+
6
+ # Sdr::Client
7
+
8
+ This is a CLI for interacting with the Stanford Digital Repository API.
9
+ The code for the SDR API server is at https://github.com/sul-dlss/sdr-api
10
+
11
+ ## Usage
12
+
13
+ Log in:
14
+ ```
15
+ sdr --service-url http://sdr-api-server:3000 login
16
+ ```
17
+
18
+
19
+ Deposit a new object:
20
+ ```
21
+ sdr --service-url https://sdr-api-server:3000 deposit --label 'hey there' \
22
+ --admin-policy 'druid:bk123gh4567' \
23
+ --collection 'druid:gh456kw9876' \
24
+ --source-id 'googlebooks:stanford_12345' file1.png file2.png
25
+ ```
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+ require 'rubocop/rake_task'
6
+
7
+ RuboCop::RakeTask.new
8
+ RSpec::Core::RakeTask.new(:spec)
9
+
10
+ desc 'Run linter and tests'
11
+ task default: %i[rubocop spec]
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'sdr/client'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require 'irb'
15
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/exe/sdr ADDED
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $LOAD_PATH.unshift 'lib'
5
+ require 'optparse'
6
+
7
+ options = {}
8
+ global = OptionParser.new do |opts|
9
+ opts.on('--service-url URL', 'Connect to the host at this URL') do |url|
10
+ options[:url] = url
11
+ end
12
+ opts.on('-h', '--help', 'Display this screen') do
13
+ puts <<~HELP
14
+ DESCRIPTION:
15
+ The SDR Command Line Interface is a tool to interact with the Stanford Digital Repository.
16
+
17
+ SYNOPSIS:
18
+ sdr [options] <command>
19
+
20
+ OPTIONS:
21
+ --service-url (string)
22
+ Override the command's default URL with the given URL.
23
+
24
+ -h, --help
25
+ Displays this screen
26
+
27
+ COMMANDS
28
+ deposit
29
+ deposit files to the SDR
30
+
31
+ login
32
+ Will prompt for email & password and exchange it for an login token, which it saves in ~/.sdr/token
33
+
34
+ HELP
35
+ exit
36
+ end
37
+ end
38
+
39
+ global.order!
40
+ command = ARGV.shift
41
+
42
+ subcommands = {
43
+ 'deposit' => OptionParser.new do |opts|
44
+ opts.on('--label LABEL', 'The object label') do |label|
45
+ options[:label] = label
46
+ end
47
+
48
+ opts.on('--admin-policy ADMIN_POLICY', 'The druid identifier of the admin policy object') do |apo|
49
+ options[:apo] = apo
50
+ end
51
+ opts.on('--collection COLLECTION', 'The druid identifier of the collection object') do |collection|
52
+ options[:collection] = collection
53
+ end
54
+
55
+ opts.on('--catkey CATKEY', 'The catkey for this item') do |catkey|
56
+ options[:catkey] = catkey
57
+ end
58
+
59
+ opts.on('--source-id SOURCE_ID', 'The source id for this object') do |source_id|
60
+ options[:source_id] = source_id
61
+ end
62
+
63
+ opts.on('-h', '--help', 'Display this screen') do
64
+ puts opts
65
+ exit
66
+ end
67
+ end,
68
+ 'login' => OptionParser.new
69
+ }
70
+
71
+ unless subcommands.key?(command)
72
+ puts "unknown command '#{command}'"
73
+ exit
74
+ end
75
+
76
+ subcommands[command].order!
77
+
78
+ require 'sdr_client'
79
+ options[:files] = ARGV unless ARGV.empty?
80
+ SdrClient::CLI.start(command, options)
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sdr_client/version'
4
+ require 'sdr_client/deposit'
5
+ require 'sdr_client/credentials'
6
+ require 'sdr_client/login'
7
+ require 'sdr_client/login_prompt'
8
+ require 'sdr_client/cli'
9
+ require 'faraday'
10
+
11
+ module SdrClient
12
+ class Error < StandardError; end
13
+ # Your code goes here...
14
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SdrClient
4
+ # The command line interface
5
+ module CLI
6
+ def self.start(command, options)
7
+ case command
8
+ when 'deposit'
9
+ SdrClient::Deposit.run(options)
10
+ when 'login'
11
+ SdrClient::Login.run(options)
12
+ else
13
+ raise "Unknown command #{command}"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SdrClient
4
+ # The stored credentials
5
+ class Credentials
6
+ # @param [String] a json string that contains a field 'token'
7
+ def self.write(body)
8
+ json = JSON.parse(body)
9
+ Dir.mkdir(credentials_path, 0o700) unless Dir.exist?(credentials_path)
10
+ File.open(credentials_file, 'w', 0o600) do |file|
11
+ file.write(json.fetch('token'))
12
+ end
13
+ puts 'Signed in.'
14
+ end
15
+
16
+ def self.read
17
+ return IO.readlines(credentials_file, chomp: true).first if File.exist?(credentials_file)
18
+
19
+ puts 'Log in first'
20
+ exit(1)
21
+ end
22
+
23
+ def self.credentials_path
24
+ @credentials_path ||= File.join(Dir.home, '.sdr')
25
+ end
26
+
27
+ def self.credentials_file
28
+ File.join(credentials_path, 'credentials')
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SdrClient
4
+ # The namespace for the "deposit" command
5
+ module Deposit
6
+ def self.run(label: nil,
7
+ type: 'http://cocina.sul.stanford.edu/models/book.jsonld',
8
+ apo:,
9
+ collection:,
10
+ catkey: nil,
11
+ source_id:,
12
+ url:, files: [])
13
+ token = Credentials.read
14
+
15
+ metadata = Request.new(label: label,
16
+ type: type,
17
+ apo: apo,
18
+ collection: collection,
19
+ source_id: source_id,
20
+ catkey: catkey)
21
+ Process.new(metadata: metadata, url: url, token: token, files: files).run
22
+ end
23
+ end
24
+ end
25
+ require 'json'
26
+ require 'sdr_client/deposit/files/direct_upload_request'
27
+ require 'sdr_client/deposit/files/direct_upload_response'
28
+ require 'sdr_client/deposit/request'
29
+ require 'sdr_client/deposit/process'
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'digest'
4
+
5
+ module SdrClient
6
+ module Deposit
7
+ module Files
8
+ DirectUploadRequest = Struct.new(:checksum, :byte_size, :content_type, :filename, keyword_init: true) do
9
+ def self.from_file(filename)
10
+ checksum = Digest::MD5.file(filename).base64digest
11
+ new(checksum: checksum,
12
+ byte_size: File.size(filename),
13
+ content_type: 'text/html',
14
+ filename: File.basename(filename))
15
+ end
16
+
17
+ def as_json
18
+ {
19
+ blob: { filename: filename, byte_size: byte_size, checksum: checksum, content_type: content_type }
20
+ }
21
+ end
22
+
23
+ def to_json(*_args)
24
+ JSON.generate(as_json)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SdrClient
4
+ module Deposit
5
+ module Files
6
+ DirectUploadResponse = Struct.new(:id, :key, :checksum, :byte_size, :content_type,
7
+ :filename, :metadata, :created_at, :direct_upload,
8
+ :signed_id, keyword_init: true)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+
5
+ module SdrClient
6
+ module Deposit
7
+ # The process for doing a deposit
8
+ class Process
9
+ BLOB_PATH = '/v1/direct_uploads'
10
+ DRO_PATH = '/v1/resources'
11
+ # @param [Request] metadata information about the object
12
+ # @param [String] url the server to send to
13
+ # @param [String] token the bearer auth token for the server
14
+ # @param [Array<String>] files a list of file names to upload
15
+ # @param [Logger] logger the logger to use
16
+ def initialize(metadata:, url:, token:, files: [], logger: Logger.new(STDOUT))
17
+ @files = files
18
+ @url = url
19
+ @token = token
20
+ @metadata = metadata
21
+ @logger = logger
22
+ end
23
+
24
+ def run
25
+ check_files_exist
26
+ file_metadata = collect_file_metadata
27
+ upload_responses = upload_file_metadata(file_metadata)
28
+ upload_files(upload_responses)
29
+ request = metadata.with_uploads(upload_responses.values)
30
+ upload_metadata(request.as_json)
31
+ end
32
+
33
+ private
34
+
35
+ attr_reader :metadata, :files, :url, :token, :logger
36
+
37
+ def check_files_exist
38
+ logger.info('checking to see if files exist')
39
+ files.each do |file_name|
40
+ raise Errno::ENOENT, file_name unless File.exist?(file_name)
41
+ end
42
+ end
43
+
44
+ def collect_file_metadata
45
+ files.each_with_object({}) do |filename, obj|
46
+ obj[filename] = Files::DirectUploadRequest.from_file(filename)
47
+ end
48
+ end
49
+
50
+ # @param [Hash<String,Files::DirectUploadRequest>] file_metadata the filenames and their upload request
51
+ def upload_file_metadata(file_metadata)
52
+ Hash[file_metadata.map { |filename, metadata| [filename, direct_upload(metadata.to_json)] }]
53
+ end
54
+
55
+ def direct_upload(metadata_json)
56
+ logger.info("Starting an upload request: #{metadata_json}")
57
+ response = connection.post(BLOB_PATH, metadata_json, 'Content-Type' => 'application/json')
58
+ raise "unexpected response: #{response.inspect}" unless response.status == 200
59
+
60
+ logger.info("Response from server: #{response.body}")
61
+
62
+ Files::DirectUploadResponse.new(JSON.parse(response.body))
63
+ end
64
+
65
+ # @param [Hash<String,Files::DirectUploadResponse>] upload_responses the filenames and their upload response
66
+ def upload_files(upload_responses)
67
+ upload_responses.each do |filename, response|
68
+ upload_file(filename: filename,
69
+ url: response.direct_upload.fetch('url'),
70
+ content_type: response.content_type,
71
+ content_length: response.byte_size)
72
+
73
+ logger.info('Upload complete')
74
+ end
75
+ end
76
+
77
+ def upload_file(filename:, url:, content_type:, content_length:)
78
+ logger.info("Uploading `#{filename}' to #{url}")
79
+
80
+ upload_response = connection.put(url) do |req|
81
+ req.body = File.open(filename)
82
+ req.headers['Content-Type'] = content_type
83
+ req.headers['Content-Length'] = content_length.to_s
84
+ end
85
+
86
+ raise "unexpected response: #{upload_response.inspect}" unless upload_response.status == 204
87
+ end
88
+
89
+ # @return [Hash<Symbol,String>] the result of the metadata call
90
+ def upload_metadata(metadata)
91
+ logger.info("Starting upload metadata: #{metadata}")
92
+ request_json = JSON.generate(metadata)
93
+ response = connection.post(DRO_PATH, request_json, 'Content-Type' => 'application/json')
94
+ unexpected_response(response) unless response.status == 201
95
+
96
+ logger.info("Response from server: #{response.body}")
97
+
98
+ { druid: JSON.parse(response.body)['druid'], background_job: response.headers['Location'] }
99
+ end
100
+
101
+ def unexpected_response(response)
102
+ raise "unexpected response: #{response.inspect}" unless response.status == 400
103
+
104
+ puts "\nThere was an error with your request: #{response.body}"
105
+ exit(1)
106
+ end
107
+
108
+ def connection
109
+ @connection ||= Faraday.new(url: url) do |conn|
110
+ conn.authorization :Bearer, token
111
+ conn.adapter :net_http
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SdrClient
4
+ module Deposit
5
+ # This represents the metadata that we send to the server for doing a deposit
6
+ class Request
7
+ # @param [String] label the required object label
8
+ # @param [String] type (http://cocina.sul.stanford.edu/models/object.jsonld) the required object type.
9
+ # @param [Array<SdrClient::Deposit::Files::DirectUploadResponse>] uploads the uploaded files to attach.
10
+ def initialize(label: nil,
11
+ apo:,
12
+ collection:,
13
+ source_id:,
14
+ catkey: nil,
15
+ type: 'http://cocina.sul.stanford.edu/models/object.jsonld',
16
+ uploads: [])
17
+ @label = label
18
+ @type = type
19
+ @source_id = source_id
20
+ @collection = collection
21
+ @catkey = catkey
22
+ @apo = apo
23
+ @uploads = uploads
24
+ end
25
+
26
+ def as_json
27
+ {
28
+ access: {},
29
+ type: type,
30
+ administrative: administrative,
31
+ identification: identification,
32
+ structural: structural
33
+ }.tap do |json|
34
+ json[:label] = label if label
35
+ end
36
+ end
37
+
38
+ # @return [Request] a clone of this request with the uploads added
39
+ def with_uploads(uploads)
40
+ Request.new(label: label,
41
+ apo: apo,
42
+ collection: collection,
43
+ source_id: source_id,
44
+ catkey: catkey,
45
+ type: type,
46
+ uploads: uploads)
47
+ end
48
+
49
+ private
50
+
51
+ attr_reader :label, :uploads, :source_id, :catkey, :apo, :collection, :type
52
+
53
+ def administrative
54
+ {
55
+ hasAdminPolicy: apo
56
+ }
57
+ end
58
+
59
+ def identification
60
+ { sourceId: source_id }.tap do |json|
61
+ json[:catkey] = catkey if catkey
62
+ end
63
+ end
64
+
65
+ def structural
66
+ {
67
+ isMemberOf: collection,
68
+ hasMember: file_sets_as_json
69
+ }
70
+ end
71
+
72
+ # In this case there is a 1-1 mapping between Files and FileSets,
73
+ # but this doesn't always have to be the case. We could change this in the
74
+ # future so that we have one FileSet that has an Image and its OCR file.
75
+ def file_sets_as_json
76
+ uploads.map do |upload|
77
+ {
78
+ "type": 'http://cocina.sul.stanford.edu/models/fileset.jsonld',
79
+ label: upload.filename,
80
+ structural: {
81
+ hasMember: [upload.signed_id]
82
+ }
83
+ }
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SdrClient
4
+ # The namespace for the "login" command
5
+ module Login
6
+ LOGIN_PATH = '/v1/auth/login'
7
+ def self.run(url:, login_service: LoginPrompt)
8
+ request_json = JSON.generate(login_service.run)
9
+ response = Faraday.post(url + LOGIN_PATH, request_json, 'Content-Type' => 'application/json')
10
+ case response.status
11
+ when 200
12
+ Credentials.write(response.body)
13
+ when 400
14
+ puts 'Email address is not a valid email'
15
+ when 401
16
+ puts 'Invalid username or password'
17
+ else
18
+ puts "Status: #{response.status}"
19
+ puts response.body
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'io/console'
4
+
5
+ module SdrClient
6
+ # The namespace for the "login" command
7
+ module LoginPrompt
8
+ def self.run
9
+ print 'Email: '
10
+ email = gets
11
+ email.strip!
12
+ print 'Password: '
13
+ password = $stdin.noecho(&:gets)
14
+ password.strip!
15
+ puts
16
+ { email: email, password: password }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SdrClient
4
+ VERSION = '0.2.0'
5
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'sdr_client/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'sdr-client'
9
+ spec.version = SdrClient::VERSION
10
+ spec.authors = ['Justin Coyne']
11
+ spec.email = ['jcoyne@justincoyne.com']
12
+
13
+ spec.summary = 'The CLI for https://github.com/sul-dlss/sdr-api'
14
+ spec.description = 'This provides a way to deposit repository objects into the Stanford Digital Repository'
15
+ spec.homepage = 'https://github.com/sul-dlss/sdr-client'
16
+
17
+ spec.metadata['homepage_uri'] = spec.homepage
18
+ spec.metadata['source_code_uri'] = 'https://github.com/sul-dlss/sdr-client'
19
+ spec.metadata['changelog_uri'] = 'https://github.com/sul-dlss/sdr-client/releases'
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
24
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ end
26
+ spec.bindir = 'exe'
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ['lib']
29
+
30
+ spec.add_dependency 'faraday', '~> 0.17.0'
31
+
32
+ spec.add_development_dependency 'bundler', '~> 2.0'
33
+ spec.add_development_dependency 'rake', '~> 13.0'
34
+ spec.add_development_dependency 'rspec', '~> 3.0'
35
+ spec.add_development_dependency 'rubocop', '~> 0.79.0'
36
+ spec.add_development_dependency 'rubocop-rspec', '~> 1.37.1'
37
+ spec.add_development_dependency 'simplecov'
38
+ spec.add_development_dependency 'webmock', '~> 3.7'
39
+ end
metadata ADDED
@@ -0,0 +1,184 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sdr-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Justin Coyne
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-01-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.17.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.17.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '13.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '13.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.79.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.79.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop-rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 1.37.1
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 1.37.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: webmock
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '3.7'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '3.7'
125
+ description: This provides a way to deposit repository objects into the Stanford Digital
126
+ Repository
127
+ email:
128
+ - jcoyne@justincoyne.com
129
+ executables:
130
+ - sdr
131
+ extensions: []
132
+ extra_rdoc_files: []
133
+ files:
134
+ - ".github/pull_request_template.md"
135
+ - ".gitignore"
136
+ - ".rspec"
137
+ - ".rubocop.yml"
138
+ - ".rubocop_todo.yml"
139
+ - ".travis.yml"
140
+ - Gemfile
141
+ - LICENSE
142
+ - README.md
143
+ - Rakefile
144
+ - bin/console
145
+ - bin/setup
146
+ - exe/sdr
147
+ - lib/sdr_client.rb
148
+ - lib/sdr_client/cli.rb
149
+ - lib/sdr_client/credentials.rb
150
+ - lib/sdr_client/deposit.rb
151
+ - lib/sdr_client/deposit/files/direct_upload_request.rb
152
+ - lib/sdr_client/deposit/files/direct_upload_response.rb
153
+ - lib/sdr_client/deposit/process.rb
154
+ - lib/sdr_client/deposit/request.rb
155
+ - lib/sdr_client/login.rb
156
+ - lib/sdr_client/login_prompt.rb
157
+ - lib/sdr_client/version.rb
158
+ - sdr-client.gemspec
159
+ homepage: https://github.com/sul-dlss/sdr-client
160
+ licenses: []
161
+ metadata:
162
+ homepage_uri: https://github.com/sul-dlss/sdr-client
163
+ source_code_uri: https://github.com/sul-dlss/sdr-client
164
+ changelog_uri: https://github.com/sul-dlss/sdr-client/releases
165
+ post_install_message:
166
+ rdoc_options: []
167
+ require_paths:
168
+ - lib
169
+ required_ruby_version: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ required_rubygems_version: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - ">="
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ requirements: []
180
+ rubygems_version: 3.0.3
181
+ signing_key:
182
+ specification_version: 4
183
+ summary: The CLI for https://github.com/sul-dlss/sdr-api
184
+ test_files: []