@kenxirwin/alma-search
Version:
Search ExLibris's Alma API for bibliographic records
128 lines (115 loc) • 3.69 kB
JavaScript
export default class SearchBibs {
constructor(params) {
const expectedKeys = ['baseUrl', 'apiKey'];
for (const key of expectedKeys) {
if (!params.hasOwnProperty(key)) {
throw new Error(`Missing required option: ${key}`);
} else if (typeof params[key] !== 'string') {
throw new Error(
`Option ${key} must be a string; received ${typeof params[key]}`
);
} else if (params[key].trim() === '') {
throw new Error(`Option ${key} cannot be an empty string`);
} else {
this[key] = params[key].trim();
}
}
}
/*
idLookup -- use any of these Alma Ids:
'mms_id', 'holdings_id', 'ie_id', 'representation_id',
'nz_mms_id', 'cz_mms_id', 'other_system_id',
Accepts comma-separated values (no spaces) for multiple items
*/
async idLookup(searchParams = {}) {
try {
this.validateBibParams(searchParams);
} catch (error) {
throw new Error(`Validation failed: ${error.message}`);
}
const apiPath = '/almaws/v1/bibs';
const url = new URL(this.baseUrl + apiPath);
for (const [key, value] of Object.entries(searchParams)) {
if (value !== undefined && value !== null) {
url.searchParams.set(key, value);
}
}
console.log(`Request URL: ${url.toString()}`);
return await this.executeFetch(url);
}
async holdingsByMmsId(mms_id) {
const apiPath = `/almaws/v1/bibs/${mms_id}/holdings`;
const url = new URL(this.baseUrl + apiPath);
console.log(`Request URL: ${url.toString()}`);
return this.executeFetch(url);
}
// this can be used for any Alma link -- the API key will be added
async followLink(inputUrl) {
const url = new URL(inputUrl);
console.log(`Request URL: ${url.toString()}`);
return this.executeFetch(url);
}
validateBibParams(params) {
const expectOneOf = [
'mms_id',
'holdings_id',
'ie_id',
'representation_id',
'nz_mms_id',
'cz_mms_id',
'other_system_id',
];
let count = 0;
for (const key of expectOneOf) {
if (params.hasOwnProperty(key)) {
if (typeof params[key] !== 'string') {
throw new Error(
`Option ${key} must be a string; received ${typeof params[key]}`
);
} else if (params[key].trim() === '') {
throw new Error(`Option ${key} cannot be an empty string`);
} else {
this[key] = params[key].trim();
count++;
}
}
}
if (count === 0) {
throw new Error(
`At least one of the following options must be provided: ${expectOneOf.join(
', '
)}`
);
}
}
async barcodeLookup(barcode) {
//accept integer or string of integers
if (barcode.toString().match(/^\d+$/) === null) {
throw new Error(
`Barcode must be a string of digits; received ${barcode}`
);
}
const apiPath = '/almaws/v1/items';
const url = new URL(this.baseUrl + apiPath);
url.searchParams.set('item_barcode', barcode);
console.log(`Request URL: ${url.toString()}`);
return await this.executeFetch(url);
}
async executeFetch(url) {
url.searchParams.set('apikey', this.apiKey);
console.log(`Requesting: ${url.toString()}`);
const response = await fetch(url.toString(), {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
});
if (!response.ok) {
const resString = JSON.stringify(response, null, 2);
throw new Error(`Network response was not ok: (${resString})`);
}
const data = await response.json();
return data;
}
}