UNPKG

internetarchive-sdk-js

Version:

NodeJS / Typescript SDK for Internet Archive APIs

83 lines (82 loc) 3.62 kB
import { ZodError } from 'zod'; import qs from 'qs'; import { IaModuleError, IaApiError } from './errors.js'; import { parseZodErrorToString } from './utils.js'; import * as schema from './schema.js'; const { ia } = schema; class HttpClient { constructor(token, options = {}) { this.checkToken = () => { if (!this.token) { throw new IaModuleError('API token required.'); } }; this.makeRequest = async (endpoint, options) => { const { path, params, body, data } = options ?? {}; if (endpoint.auth) this.checkToken(); const baseUrl = endpoint.baseUrl; const apiUrl = baseUrl + (path ? `/${path}` : '') + (params ? `?${new URLSearchParams(params)}` : ''); const headers = { ...(endpoint.auth && { authorization: `LOW ${this.token}` }), ...options?.headers, }; try { ia.Options.parse(this.options); } catch (err) { if (err instanceof ZodError) { const error = 'Invalid options args: ' + parseZodErrorToString(err); throw new IaModuleError(error); } } try { if (data && body) { throw new IaModuleError('Cannot pass data and body data at the same time.'); } if (endpoint?.schema) { try { if (endpoint.schema.type === 'headers') schema?.[endpoint.schema.name].parse(headers); if (endpoint.schema.type === 'data') schema?.[endpoint.schema.name].parse(data); if (endpoint.schema.type === 'qs') schema?.[endpoint.schema.name].parse(data); if (endpoint.schema.type === 'body') schema?.[endpoint.schema.name].parse(body); } catch (err) { if (err instanceof ZodError) { console.error(err); const error = `Invalid ${endpoint.schema.name} - ${parseZodErrorToString(err)}`; throw new IaModuleError(error); } } } const response = await fetch(apiUrl, { headers, method: endpoint.method, ...(body && { body: JSON.stringify(body) }), ...(data && { body: endpoint.schema.type === 'qs' ? qs.stringify(data) : data }), }); if (!response.ok) { const message = response.status === 403 ? 'archive.org token is incorrect or you do not have access to this collection.' : endpoint?.emptyBody ? response.statusText : JSON.parse(await response.text())?.error ?? response.statusText; throw new IaApiError(message, response.status); } else { return endpoint?.emptyBody ? { status: response?.status, } : await response.json(); } } catch (err) { throw new IaApiError(err?.cause?.message ?? err?.message, err.statusCode); } }; this.token = token; this.options = options; } } export default HttpClient;