berkeley_library-tind 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/build.yml +18 -0
- data/.gitignore +388 -0
- data/.idea/inspectionProfiles/Project_Default.xml +20 -0
- data/.idea/misc.xml +4 -0
- data/.idea/modules.xml +8 -0
- data/.idea/tind.iml +138 -0
- data/.idea/vcs.xml +6 -0
- data/.rubocop.yml +334 -0
- data/.ruby-version +1 -0
- data/.simplecov +8 -0
- data/.yardopts +1 -0
- data/CHANGES.md +58 -0
- data/Dockerfile +57 -0
- data/Gemfile +3 -0
- data/Jenkinsfile +18 -0
- data/LICENSE.md +21 -0
- data/README.md +73 -0
- data/Rakefile +20 -0
- data/berkeley_library-tind.gemspec +50 -0
- data/bin/tind-export +14 -0
- data/docker-compose.yml +15 -0
- data/lib/berkeley_library/tind.rb +3 -0
- data/lib/berkeley_library/tind/api.rb +1 -0
- data/lib/berkeley_library/tind/api/api.rb +132 -0
- data/lib/berkeley_library/tind/api/api_exception.rb +131 -0
- data/lib/berkeley_library/tind/api/collection.rb +82 -0
- data/lib/berkeley_library/tind/api/date_range.rb +67 -0
- data/lib/berkeley_library/tind/api/format.rb +32 -0
- data/lib/berkeley_library/tind/api/search.rb +100 -0
- data/lib/berkeley_library/tind/config.rb +103 -0
- data/lib/berkeley_library/tind/export.rb +1 -0
- data/lib/berkeley_library/tind/export/column.rb +54 -0
- data/lib/berkeley_library/tind/export/column_group.rb +144 -0
- data/lib/berkeley_library/tind/export/column_group_list.rb +131 -0
- data/lib/berkeley_library/tind/export/column_width_calculator.rb +76 -0
- data/lib/berkeley_library/tind/export/config.rb +154 -0
- data/lib/berkeley_library/tind/export/csv_exporter.rb +29 -0
- data/lib/berkeley_library/tind/export/export.rb +47 -0
- data/lib/berkeley_library/tind/export/export_command.rb +168 -0
- data/lib/berkeley_library/tind/export/export_exception.rb +8 -0
- data/lib/berkeley_library/tind/export/export_format.rb +67 -0
- data/lib/berkeley_library/tind/export/exporter.rb +105 -0
- data/lib/berkeley_library/tind/export/filter.rb +52 -0
- data/lib/berkeley_library/tind/export/no_results_error.rb +7 -0
- data/lib/berkeley_library/tind/export/ods_exporter.rb +138 -0
- data/lib/berkeley_library/tind/export/row.rb +24 -0
- data/lib/berkeley_library/tind/export/row_metrics.rb +18 -0
- data/lib/berkeley_library/tind/export/table.rb +175 -0
- data/lib/berkeley_library/tind/export/table_metrics.rb +116 -0
- data/lib/berkeley_library/tind/marc.rb +1 -0
- data/lib/berkeley_library/tind/marc/xml_reader.rb +144 -0
- data/lib/berkeley_library/tind/module_info.rb +14 -0
- data/lib/berkeley_library/util/arrays.rb +178 -0
- data/lib/berkeley_library/util/logging.rb +1 -0
- data/lib/berkeley_library/util/ods/spreadsheet.rb +170 -0
- data/lib/berkeley_library/util/ods/xml/content_doc.rb +26 -0
- data/lib/berkeley_library/util/ods/xml/document_node.rb +57 -0
- data/lib/berkeley_library/util/ods/xml/element_node.rb +106 -0
- data/lib/berkeley_library/util/ods/xml/loext/table_protection.rb +26 -0
- data/lib/berkeley_library/util/ods/xml/manifest/file_entry.rb +42 -0
- data/lib/berkeley_library/util/ods/xml/manifest/manifest.rb +73 -0
- data/lib/berkeley_library/util/ods/xml/manifest_doc.rb +26 -0
- data/lib/berkeley_library/util/ods/xml/namespace.rb +46 -0
- data/lib/berkeley_library/util/ods/xml/office/automatic_styles.rb +181 -0
- data/lib/berkeley_library/util/ods/xml/office/body.rb +17 -0
- data/lib/berkeley_library/util/ods/xml/office/document_content.rb +98 -0
- data/lib/berkeley_library/util/ods/xml/office/document_styles.rb +39 -0
- data/lib/berkeley_library/util/ods/xml/office/font_face_decls.rb +30 -0
- data/lib/berkeley_library/util/ods/xml/office/scripts.rb +17 -0
- data/lib/berkeley_library/util/ods/xml/office/spreadsheet.rb +37 -0
- data/lib/berkeley_library/util/ods/xml/office/styles.rb +39 -0
- data/lib/berkeley_library/util/ods/xml/style/cell_style.rb +58 -0
- data/lib/berkeley_library/util/ods/xml/style/column_style.rb +36 -0
- data/lib/berkeley_library/util/ods/xml/style/default_style.rb +31 -0
- data/lib/berkeley_library/util/ods/xml/style/family.rb +85 -0
- data/lib/berkeley_library/util/ods/xml/style/font_face.rb +46 -0
- data/lib/berkeley_library/util/ods/xml/style/paragraph_properties.rb +30 -0
- data/lib/berkeley_library/util/ods/xml/style/row_style.rb +37 -0
- data/lib/berkeley_library/util/ods/xml/style/style.rb +44 -0
- data/lib/berkeley_library/util/ods/xml/style/table_cell_properties.rb +40 -0
- data/lib/berkeley_library/util/ods/xml/style/table_column_properties.rb +30 -0
- data/lib/berkeley_library/util/ods/xml/style/table_properties.rb +25 -0
- data/lib/berkeley_library/util/ods/xml/style/table_row_properties.rb +28 -0
- data/lib/berkeley_library/util/ods/xml/style/table_style.rb +27 -0
- data/lib/berkeley_library/util/ods/xml/style/text_properties.rb +52 -0
- data/lib/berkeley_library/util/ods/xml/styles_doc.rb +26 -0
- data/lib/berkeley_library/util/ods/xml/table/named_expressions.rb +17 -0
- data/lib/berkeley_library/util/ods/xml/table/repeatable.rb +38 -0
- data/lib/berkeley_library/util/ods/xml/table/table.rb +193 -0
- data/lib/berkeley_library/util/ods/xml/table/table_cell.rb +46 -0
- data/lib/berkeley_library/util/ods/xml/table/table_column.rb +43 -0
- data/lib/berkeley_library/util/ods/xml/table/table_row.rb +136 -0
- data/lib/berkeley_library/util/ods/xml/text/p.rb +118 -0
- data/lib/berkeley_library/util/paths.rb +111 -0
- data/lib/berkeley_library/util/stringios.rb +30 -0
- data/lib/berkeley_library/util/strings.rb +42 -0
- data/lib/berkeley_library/util/sys_exits.rb +15 -0
- data/lib/berkeley_library/util/times.rb +22 -0
- data/lib/berkeley_library/util/uris.rb +44 -0
- data/lib/berkeley_library/util/uris/appender.rb +162 -0
- data/lib/berkeley_library/util/uris/requester.rb +62 -0
- data/lib/berkeley_library/util/uris/validator.rb +32 -0
- data/rakelib/bundle.rake +8 -0
- data/rakelib/coverage.rake +11 -0
- data/rakelib/gem.rake +54 -0
- data/rakelib/rubocop.rake +18 -0
- data/rakelib/spec.rake +2 -0
- data/spec/.rubocop.yml +40 -0
- data/spec/berkeley_library/tind/api/api_exception_spec.rb +91 -0
- data/spec/berkeley_library/tind/api/api_spec.rb +143 -0
- data/spec/berkeley_library/tind/api/collection_spec.rb +74 -0
- data/spec/berkeley_library/tind/api/date_range_spec.rb +110 -0
- data/spec/berkeley_library/tind/api/format_spec.rb +54 -0
- data/spec/berkeley_library/tind/api/search_spec.rb +364 -0
- data/spec/berkeley_library/tind/config_spec.rb +86 -0
- data/spec/berkeley_library/tind/export/column_group_spec.rb +29 -0
- data/spec/berkeley_library/tind/export/column_spec.rb +43 -0
- data/spec/berkeley_library/tind/export/config_spec.rb +206 -0
- data/spec/berkeley_library/tind/export/export_command_spec.rb +169 -0
- data/spec/berkeley_library/tind/export/export_format_spec.rb +59 -0
- data/spec/berkeley_library/tind/export/export_matcher.rb +112 -0
- data/spec/berkeley_library/tind/export/export_spec.rb +150 -0
- data/spec/berkeley_library/tind/export/exporter_spec.rb +125 -0
- data/spec/berkeley_library/tind/export/row_spec.rb +118 -0
- data/spec/berkeley_library/tind/export/table_spec.rb +322 -0
- data/spec/berkeley_library/tind/marc/xml_reader_spec.rb +93 -0
- data/spec/berkeley_library/util/arrays_spec.rb +340 -0
- data/spec/berkeley_library/util/ods/spreadsheet_spec.rb +124 -0
- data/spec/berkeley_library/util/ods/xml/content_doc_spec.rb +121 -0
- data/spec/berkeley_library/util/ods/xml/manifest/file_entry_spec.rb +27 -0
- data/spec/berkeley_library/util/ods/xml/manifest/manifest_spec.rb +33 -0
- data/spec/berkeley_library/util/ods/xml/office/document_content_spec.rb +60 -0
- data/spec/berkeley_library/util/ods/xml/style/automatic_styles_spec.rb +37 -0
- data/spec/berkeley_library/util/ods/xml/style/family_spec.rb +57 -0
- data/spec/berkeley_library/util/ods/xml/table/table_row_spec.rb +179 -0
- data/spec/berkeley_library/util/ods/xml/table/table_spec.rb +218 -0
- data/spec/berkeley_library/util/paths_spec.rb +90 -0
- data/spec/berkeley_library/util/stringios_spec.rb +34 -0
- data/spec/berkeley_library/util/strings_spec.rb +27 -0
- data/spec/berkeley_library/util/times_spec.rb +39 -0
- data/spec/berkeley_library/util/uris_spec.rb +118 -0
- data/spec/data/collection-names.txt +438 -0
- data/spec/data/collections.json +4827 -0
- data/spec/data/disjoint-records.xml +187 -0
- data/spec/data/record-184453.xml +58 -0
- data/spec/data/record-184458.xml +63 -0
- data/spec/data/record-187888.xml +78 -0
- data/spec/data/records-api-search-cjk-p1.xml +6381 -0
- data/spec/data/records-api-search-cjk-p2.xml +5 -0
- data/spec/data/records-api-search-p1.xml +4506 -0
- data/spec/data/records-api-search-p2.xml +4509 -0
- data/spec/data/records-api-search-p3.xml +4506 -0
- data/spec/data/records-api-search-p4.xml +4509 -0
- data/spec/data/records-api-search-p5.xml +4506 -0
- data/spec/data/records-api-search-p6.xml +2436 -0
- data/spec/data/records-api-search-p7.xml +5 -0
- data/spec/data/records-api-search.xml +234 -0
- data/spec/data/records-manual-search.xml +547 -0
- data/spec/spec_helper.rb +30 -0
- data/test/profile/table_from_records_profile.rb +46 -0
- metadata +585 -0
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.7
|
data/.simplecov
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--no-private --protected lib/**/*.rb -m markdown
|
data/CHANGES.md
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# 0.4.0 (2021-08-19)
|
2
|
+
|
3
|
+
- Rename to `BerkeleyLibrary::TIND` in prep for move to GitHub
|
4
|
+
|
5
|
+
# 0.3.3 (2021-08-05)
|
6
|
+
|
7
|
+
- Send a custom `User-Agent` header to deal with new TIND firewall rules.
|
8
|
+
|
9
|
+
# 0.3.2 (2021-07-29)
|
10
|
+
|
11
|
+
- Loosen `spec.required_ruby_version` to support Ruby 3.x
|
12
|
+
|
13
|
+
# 0.3.1 (2021-05-17)
|
14
|
+
|
15
|
+
- `API#get` now raises an `APIException` with a simulated '404 Not Found'
|
16
|
+
status if `UCBLIT::TIND::Config.base_uri` is not set, or is blank.
|
17
|
+
|
18
|
+
# 0.3.0 (2021-05-11)
|
19
|
+
|
20
|
+
- Extracts `MARCExtensions` into a separate gem,
|
21
|
+
[`ucblit-marc`](https://git.lib.berkeley.edu/lap/ucblit-marc/edit).
|
22
|
+
|
23
|
+
# 0.2.4 (2021-05-06)
|
24
|
+
|
25
|
+
- `API#get` now raises an `APIException` with a simulated '401 Unauthorized' status
|
26
|
+
if `UCBLIT::TIND::Config.api_key` is not set.
|
27
|
+
|
28
|
+
# 0.2.3 (2021-05-04)
|
29
|
+
|
30
|
+
- `UCBLIT::TIND::Export`:
|
31
|
+
- new method `#exporter_for` returns a `UCBLIT::TIND::Exporter` but doesn't
|
32
|
+
export immediately.
|
33
|
+
- `#export` now raises `NoResultsError` if no records are returned.
|
34
|
+
|
35
|
+
- `UCBLIT::TIND::Exporter` exposes an `any_results?` method that returns false if
|
36
|
+
there are no results to export.
|
37
|
+
|
38
|
+
# 0.2.2 (2021-05-03)
|
39
|
+
|
40
|
+
- `UCBLIT::TIND::API::Search` now gracefully returns an empty result when it gets the 500 Internal
|
41
|
+
Server Error that TIND thinks is an acceptable empty search result, instead of raising an exception.
|
42
|
+
|
43
|
+
# 0.2.1 (2021-04-02)
|
44
|
+
|
45
|
+
- `bin/tind-export` script now supports passing an environment file on the command line with the
|
46
|
+
`-e` option; `-e` with no arguments reads from `.env` in the current working directory.
|
47
|
+
- Table metrics (font size, line height, max column width etc.) can now be customized
|
48
|
+
with environment variables (see [`UCBLIT::TIND::Export::Config`](lib/berkeley_library/tind/export/config.rb))
|
49
|
+
|
50
|
+
# 0.2.0 (2021-03-31)
|
51
|
+
|
52
|
+
- Columns in exported OpenOffice / LibreOffice that should not be edited are now marked
|
53
|
+
in red but **not** protected.
|
54
|
+
- API key configuration has moved from `UCBLIT::TIND::API` to `UCBLIT::TIND::Config`.
|
55
|
+
|
56
|
+
# 0.1.0 (2021-03-12)
|
57
|
+
|
58
|
+
- Initial prerelease
|
data/Dockerfile
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# =============================================================================
|
2
|
+
# Target: base
|
3
|
+
|
4
|
+
FROM ruby:2.7-alpine AS base
|
5
|
+
|
6
|
+
RUN apk --no-cache --update upgrade && \
|
7
|
+
apk --no-cache add \
|
8
|
+
bash \
|
9
|
+
ca-certificates \
|
10
|
+
git \
|
11
|
+
libc6-compat \
|
12
|
+
openssl \
|
13
|
+
tzdata \
|
14
|
+
xz-libs \
|
15
|
+
&& rm -rf /var/cache/apk/*
|
16
|
+
|
17
|
+
WORKDIR /opt/app
|
18
|
+
|
19
|
+
# =============================================================================
|
20
|
+
# Target: development
|
21
|
+
#
|
22
|
+
|
23
|
+
FROM base AS development
|
24
|
+
|
25
|
+
# Install system packages needed to build gems with C extensions.
|
26
|
+
RUN apk --update --no-cache add \
|
27
|
+
build-base \
|
28
|
+
coreutils \
|
29
|
+
git \
|
30
|
+
&& rm -rf /var/cache/apk/*
|
31
|
+
|
32
|
+
# The base image ships bundler 1.17.2, but we want something more recent
|
33
|
+
RUN gem install bundler -v 2.1.4
|
34
|
+
|
35
|
+
# Copy codebase to WORKDIR. Unlike application projects, for a gem project
|
36
|
+
# we need to do this before running `bundle install`, in order for the gem
|
37
|
+
# we're building to be able to "install" itself.
|
38
|
+
COPY . .
|
39
|
+
|
40
|
+
# Install gems.
|
41
|
+
RUN bundle install --path=/usr/local/bundle
|
42
|
+
|
43
|
+
# =============================================================================
|
44
|
+
# Target: production
|
45
|
+
|
46
|
+
FROM base AS production
|
47
|
+
|
48
|
+
# Copy the built codebase from the dev stage
|
49
|
+
COPY --from=development /opt/app /opt/app
|
50
|
+
COPY --from=development /usr/local/bundle /usr/local/bundle
|
51
|
+
|
52
|
+
# Sanity-check that everything was installed correctly and still runs in the
|
53
|
+
# slimmed-down production image.
|
54
|
+
RUN bundle config set deployment 'true'
|
55
|
+
RUN bundle install --local --path=/usr/local/bundle
|
56
|
+
|
57
|
+
CMD ['bundle', 'exec', 'rake']
|
data/Gemfile
ADDED
data/Jenkinsfile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env groovy
|
2
|
+
|
3
|
+
dockerComposePipeline(
|
4
|
+
commands: [
|
5
|
+
'bundle exec rake coverage',
|
6
|
+
'bundle exec rake rubocop',
|
7
|
+
'bundle exec rake bundle:audit',
|
8
|
+
'bundle exec rake gem'
|
9
|
+
],
|
10
|
+
artifacts: [
|
11
|
+
junit: 'artifacts/rspec/**/*.xml',
|
12
|
+
html : [
|
13
|
+
'Code Coverage': 'artifacts/rcov',
|
14
|
+
'RuboCop' : 'artifacts/rubocop'
|
15
|
+
],
|
16
|
+
raw : ['artifacts/**/*.gem']
|
17
|
+
]
|
18
|
+
)
|
data/LICENSE.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright © 2021 The Regents of the University of California
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a
|
6
|
+
copy of this software and associated documentation files (the “Software”),
|
7
|
+
to deal in the Software without restriction, including without limitation
|
8
|
+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
9
|
+
and/or sell copies of the Software, and to permit persons to whom the
|
10
|
+
Software is furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
20
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
21
|
+
DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
# BerkeleyLibrary::TIND
|
2
|
+
|
3
|
+
[![Build Status](https://github.com/BerkeleyLibrary/tind/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/BerkeleyLibrary/tind/actions/workflows/build.yml)
|
4
|
+
[![Gem Version](https://img.shields.io/gem/v/berkeley_library-tind.svg)](https://github.com/BerkeleyLibrary/tind/releases)
|
5
|
+
|
6
|
+
Utility gem for working with the TIND DA digital archive.
|
7
|
+
|
8
|
+
## Configuration
|
9
|
+
|
10
|
+
To access the TIND API, you will need to set:
|
11
|
+
|
12
|
+
1. the base URL for your TIND installation (e.g. `https://digicoll.lib.berkeley.edu/`)
|
13
|
+
2. the TIND API key (see the "[API Token Generator](https://docs.tind.io/article/2xaplzx9cn-api-token-generator)"
|
14
|
+
article on [`docs.tind.io`](https://docs.tind.io). TIND's code and
|
15
|
+
docs are inconsistent in their use of "token" and "key". The UI calls
|
16
|
+
it a "key", so that's the term we use here.)
|
17
|
+
|
18
|
+
These can be set directly, via accessors in the `BerkeleyLibrary::TIND::Config` module;
|
19
|
+
if they are not set, a value will be read from the environment, and if no
|
20
|
+
value is present in the environment and Rails is loaded, from the Rails
|
21
|
+
application configuration (`Rails.application.config`).
|
22
|
+
|
23
|
+
| Value | Config | ENV | Rails |
|
24
|
+
| --- | --- | --- | --- |
|
25
|
+
| TIND base URI | `:base_uri` | `LIT_TIND_BASE_URL` | `:tind_base_uri` |
|
26
|
+
| API key | `:api_key` | `LIT_TIND_API_KEY` | `:tind_api_key` |
|
27
|
+
|
28
|
+
**Note:** The TIND base URI can be set either as a string or as a `URI`
|
29
|
+
object, but will always be returned as a `URI` object, and an invalid
|
30
|
+
string setting will raise `URI::InvalidURIError`.
|
31
|
+
|
32
|
+
## Command-line tool: `tind-export`
|
33
|
+
|
34
|
+
The `tind-export` command allows you to list TIND collections, or to
|
35
|
+
export a TIND collection from the command line. (If the gem is installed,
|
36
|
+
`tind-export` should be in your `$PATH`. If you've cloned the gem source,
|
37
|
+
you can invoke it with `bin/tind-export` from the project root directory.)
|
38
|
+
|
39
|
+
Examples:
|
40
|
+
|
41
|
+
1. list collections
|
42
|
+
|
43
|
+
```sh
|
44
|
+
tind-export --list-collections
|
45
|
+
```
|
46
|
+
|
47
|
+
2. export a collection as an OpenOffice/LibreOffice spreadsheet
|
48
|
+
|
49
|
+
```sh
|
50
|
+
tind-export -o lincoln-papers.ods 'Abraham Lincoln Papers'
|
51
|
+
```
|
52
|
+
|
53
|
+
3. export a collection as an OpenOffice/LibreOffice spreadsheet in exploded XML format,
|
54
|
+
where `lincoln-papers` is a directory
|
55
|
+
|
56
|
+
```sh
|
57
|
+
tind-export -f ODS -o lincoln-papers 'Abraham Lincoln Papers'
|
58
|
+
```
|
59
|
+
|
60
|
+
(Note that OpenOffice itself and many other tools get confused by the extra text
|
61
|
+
nodes in the pretty-printed files and won't read them properly; this feature
|
62
|
+
is mostly for debugging.)
|
63
|
+
|
64
|
+
4. export a collection as CSV, to standard output
|
65
|
+
|
66
|
+
```sh
|
67
|
+
tind-export -f CSV 'Abraham Lincoln Papers'
|
68
|
+
```
|
69
|
+
|
70
|
+
For the full list of options, type `tind-export --help`. Note that you can set
|
71
|
+
the TIND base URL and API key either via the environment, as above, or as options
|
72
|
+
passed to the `tind-export` command. If both an explicit option and an environment
|
73
|
+
variable are set for either, the explicit option takes precedence.
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('Gemfile', __dir__)
|
2
|
+
require 'bundler/setup' # Set up gems listed in the Gemfile.
|
3
|
+
|
4
|
+
# ------------------------------------------------------------
|
5
|
+
# Application code
|
6
|
+
|
7
|
+
File.expand_path('lib', __dir__).tap do |lib|
|
8
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
9
|
+
end
|
10
|
+
|
11
|
+
# ------------------------------------------------------------
|
12
|
+
# CI
|
13
|
+
|
14
|
+
ENV['RAILS_ENV'] = 'test' if ENV['CI']
|
15
|
+
|
16
|
+
# ------------------------------------------------------------
|
17
|
+
# Custom tasks
|
18
|
+
|
19
|
+
desc 'Run tests, check test coverage, check code style, check for vulnerabilities, build gem'
|
20
|
+
task default: %i[coverage rubocop bundle:audit gem]
|
@@ -0,0 +1,50 @@
|
|
1
|
+
File.expand_path('lib', __dir__).tap do |lib|
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
end
|
4
|
+
|
5
|
+
ruby_version = '>= 2.7'
|
6
|
+
|
7
|
+
require 'berkeley_library/tind/module_info'
|
8
|
+
|
9
|
+
Gem::Specification.new do |spec|
|
10
|
+
spec.name = BerkeleyLibrary::TIND::ModuleInfo::NAME
|
11
|
+
spec.author = BerkeleyLibrary::TIND::ModuleInfo::AUTHOR
|
12
|
+
spec.email = BerkeleyLibrary::TIND::ModuleInfo::AUTHOR_EMAIL
|
13
|
+
spec.summary = BerkeleyLibrary::TIND::ModuleInfo::SUMMARY
|
14
|
+
spec.description = BerkeleyLibrary::TIND::ModuleInfo::DESCRIPTION
|
15
|
+
spec.license = BerkeleyLibrary::TIND::ModuleInfo::LICENSE
|
16
|
+
spec.version = BerkeleyLibrary::TIND::ModuleInfo::VERSION
|
17
|
+
spec.homepage = BerkeleyLibrary::TIND::ModuleInfo::HOMEPAGE
|
18
|
+
|
19
|
+
spec.files = `git ls-files -z`.split("\x0")
|
20
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
|
+
spec.require_paths = ['lib']
|
22
|
+
spec.executables << 'tind-export'
|
23
|
+
|
24
|
+
spec.required_ruby_version = ruby_version
|
25
|
+
|
26
|
+
spec.add_dependency 'berkeley_library-logging', '~> 0.2'
|
27
|
+
spec.add_dependency 'berkeley_library-marc', '~> 0.2'
|
28
|
+
spec.add_dependency 'ice_nine', '~> 0.11'
|
29
|
+
spec.add_dependency 'marc', '~> 1.0'
|
30
|
+
spec.add_dependency 'rchardet', '~> 1.8'
|
31
|
+
spec.add_dependency 'rest-client', '~> 2.1'
|
32
|
+
spec.add_dependency 'rubyzip', '~> 2.3'
|
33
|
+
spec.add_dependency 'typesafe_enum', '~> 0.3'
|
34
|
+
|
35
|
+
spec.add_development_dependency 'bundle-audit', '~> 0.1'
|
36
|
+
spec.add_development_dependency 'ci_reporter_rspec', '~> 1.0'
|
37
|
+
spec.add_development_dependency 'colorize', '~> 0.8'
|
38
|
+
spec.add_development_dependency 'dotenv', '~> 2.7'
|
39
|
+
spec.add_development_dependency 'listen', '>= 3.0.5', '< 3.2'
|
40
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
41
|
+
spec.add_development_dependency 'roo', '~> 2.8'
|
42
|
+
spec.add_development_dependency 'rspec', '~> 3.10'
|
43
|
+
spec.add_development_dependency 'rubocop', '= 1.11'
|
44
|
+
spec.add_development_dependency 'rubocop-rake', '~> 0.5'
|
45
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 2.2'
|
46
|
+
spec.add_development_dependency 'ruby-prof', '~> 0.17.0'
|
47
|
+
spec.add_development_dependency 'simplecov', '~> 0.21'
|
48
|
+
spec.add_development_dependency 'simplecov-rcov', '~> 0.2'
|
49
|
+
spec.add_development_dependency 'webmock', '~> 3.12'
|
50
|
+
end
|
data/bin/tind-export
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
begin
|
4
|
+
# This should work if (1) the gem is installed, or
|
5
|
+
# (2) we're in development and used `bundle exec`
|
6
|
+
require 'berkeley_library/tind'
|
7
|
+
rescue LoadError
|
8
|
+
# If we're in development, `require 'bundler/setup'`
|
9
|
+
# is roughly equivalent to `bundle exec`
|
10
|
+
require 'bundler/setup'
|
11
|
+
require 'berkeley_library/tind'
|
12
|
+
end
|
13
|
+
|
14
|
+
BerkeleyLibrary::TIND::Export::ExportCommand.new(*ARGV).execute!
|
data/docker-compose.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
services:
|
2
|
+
gem:
|
3
|
+
build:
|
4
|
+
context: .
|
5
|
+
target: development
|
6
|
+
ports:
|
7
|
+
- target: 3000
|
8
|
+
published: 3000
|
9
|
+
restart: always
|
10
|
+
volumes:
|
11
|
+
# Note that this mounts the *entire* repo directory (including
|
12
|
+
# files ignored in .dockerignore when building the image)
|
13
|
+
- ./:/opt/app
|
14
|
+
|
15
|
+
version: "3.7"
|
@@ -0,0 +1 @@
|
|
1
|
+
Dir.glob(File.expand_path('api/*.rb', __dir__)).sort.each(&method(:require))
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
require 'berkeley_library/util/uris'
|
5
|
+
require 'berkeley_library/util/logging'
|
6
|
+
require 'berkeley_library/tind/config'
|
7
|
+
require 'berkeley_library/tind/api/api_exception'
|
8
|
+
|
9
|
+
module BerkeleyLibrary
|
10
|
+
module TIND
|
11
|
+
module API
|
12
|
+
class << self
|
13
|
+
include BerkeleyLibrary::Util
|
14
|
+
include BerkeleyLibrary::Logging
|
15
|
+
|
16
|
+
# Gets the TIND API key.
|
17
|
+
# @return [String, nil] the TIND API key, or `nil` if not set.
|
18
|
+
def api_key
|
19
|
+
BerkeleyLibrary::TIND::Config.api_key
|
20
|
+
end
|
21
|
+
|
22
|
+
# Gets the value to send in the User-Agent header
|
23
|
+
# @return [String] the user agent
|
24
|
+
def user_agent
|
25
|
+
BerkeleyLibrary::TIND::Config.user_agent
|
26
|
+
end
|
27
|
+
|
28
|
+
# Gets the API base URI.
|
29
|
+
# @return [URI] the API base URI
|
30
|
+
def api_base_uri
|
31
|
+
return if Config.blank?((base_uri = Config.base_uri))
|
32
|
+
|
33
|
+
URIs.append(base_uri, '/api/v1')
|
34
|
+
end
|
35
|
+
|
36
|
+
# Gets the URI for the specified API endpoint.
|
37
|
+
# @param endpoint [Symbol, String] the endpoint (e.g. `:search` or `:collection`)
|
38
|
+
# @return [URI] the URI for the specified endpoint
|
39
|
+
# @raise [API::BaseURINotSet] if the TIND base URI is not set
|
40
|
+
def uri_for(endpoint)
|
41
|
+
return if Config.blank?(api_base_uri)
|
42
|
+
|
43
|
+
URIs.append(api_base_uri, endpoint)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Makes a GET request.
|
47
|
+
#
|
48
|
+
# @overload get(endpoint, **params)
|
49
|
+
# Makes a GET request to the specified endpoint with the specified parameters,
|
50
|
+
# and returns the response body as a string. Example:
|
51
|
+
#
|
52
|
+
# ```ruby
|
53
|
+
# marc_xml = API.get(:search, c: 'The Bancroft Library')
|
54
|
+
# XMLReader.new(marc_xml).each { |record| ... }
|
55
|
+
# ```
|
56
|
+
#
|
57
|
+
# @param endpoint [Symbol] the API endpoint, e.g. `:search` or `:collection`
|
58
|
+
# @param **params [Hash] the query parameters
|
59
|
+
# @return [String] the response body
|
60
|
+
# @overload get(endpoint, **params, &block)
|
61
|
+
# Makes a GET request to the specified endpoint with the specified parameters,
|
62
|
+
# and yields an `IO` that streams the response body. Example:
|
63
|
+
#
|
64
|
+
# ```ruby
|
65
|
+
# API.get(:search, c: 'The Bancroft Library') do |body|
|
66
|
+
# XMLReader.new(body).each { |record| ... }
|
67
|
+
# end
|
68
|
+
# ```
|
69
|
+
#
|
70
|
+
# @param endpoint [Symbol, String] the API endpoint, e.g. `:search` or `:collections`
|
71
|
+
# @param **params [Hash] the query parameters
|
72
|
+
# @yieldparam body [IO] the response body, as an IO stream
|
73
|
+
def get(endpoint, **params, &block)
|
74
|
+
endpoint_uri = uri_for(endpoint)
|
75
|
+
raise BaseURINotSet.new(endpoint, params) if Config.blank?(endpoint_uri)
|
76
|
+
|
77
|
+
logger.debug(format_request(endpoint_uri, params))
|
78
|
+
|
79
|
+
body = do_get(endpoint_uri, params)
|
80
|
+
return body unless block_given?
|
81
|
+
|
82
|
+
stream_response_body(body, &block)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Returns a formatted string version of the request, suitable for
|
86
|
+
# logging or error messages.
|
87
|
+
#
|
88
|
+
# @param uri [URI, String] the URI
|
89
|
+
# @param params [Hash, nil] the query parameters
|
90
|
+
# @param method [String] the request method
|
91
|
+
def format_request(uri, params = nil, method = 'GET')
|
92
|
+
query_string = format_query(params)
|
93
|
+
uri = URIs.append(uri, '?', query_string) if query_string
|
94
|
+
|
95
|
+
"#{method} #{uri}"
|
96
|
+
end
|
97
|
+
|
98
|
+
def format_query(params)
|
99
|
+
return unless params
|
100
|
+
return URI.encode_www_form(params.to_hash) if params.respond_to?(:to_hash)
|
101
|
+
|
102
|
+
raise ArgumentError, "Argument #{params.inspect} does not appear to be a set of query parameters"
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def do_get(endpoint_uri, params)
|
108
|
+
raise APIKeyNotSet.new(endpoint_uri, params) if Config.blank?(api_key)
|
109
|
+
|
110
|
+
begin
|
111
|
+
URIs.get(endpoint_uri, params, {
|
112
|
+
'Authorization' => "Token #{api_key}",
|
113
|
+
'User-Agent' => user_agent
|
114
|
+
})
|
115
|
+
rescue RestClient::RequestFailed => e
|
116
|
+
raise APIException.wrap(e, url: endpoint_uri, params: params)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# TODO: make real body streaming work
|
121
|
+
def stream_response_body(body)
|
122
|
+
yield StringIO.new(body)
|
123
|
+
rescue StandardError => e
|
124
|
+
# We don't log the full stack trace here as we assume the block will do that
|
125
|
+
logger.warn("Error yielding response body: #{e}: body was: #{body}")
|
126
|
+
raise
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|