OpenLibrary Client
A modern TypeScript API wrapper for the OpenLibrary REST API, designed to provide a clean and type-safe interface for JavaScript and TypeScript developers.
Features
- 🚀 Modern TypeScript: Full type safety with comprehensive interfaces and IntelliSense support
- 📦 Minimal Dependencies: Built with only axios for HTTP requests
- 🛡️ Error Handling: Robust error handling with detailed typed error responses
- 🔧 Configurable: Flexible configuration options with type validation
- 📚 Well Documented: Comprehensive documentation and TypeScript examples
- 🎯 Focused: Clean API surface focused on essential functionality
- 💡 Developer Experience: Auto-completion, type checking, and inline documentation
Installation
npm install open-library-client
yarn add open-library-client
pnpm add open-library-client
Quick Start
import { OpenLibraryClient, BookSearchParams, ApiResponse, BookSearchResponse } from 'open-library-client';
// Create a client instance with configuration
const client = new OpenLibraryClient({
timeout: 15000,
headers: {
'User-Agent': 'MyApp/1.0.0'
}
});
// Search for books with full type safety
const searchParams: BookSearchParams = {
q: 'The Lord of the Rings',
author: 'Tolkien',
limit: 5
};
const results: ApiResponse<BookSearchResponse> = await client.searchBooks(searchParams);
console.log(`Found ${results.data.numFound} books`);
results.data.docs.forEach(book => {
console.log(`${book.title} by ${book.author_name?.join(', ')}`);
});
Examples
For comprehensive usage examples including complete workflows from search to book details and cover images, see the examples/
folder in the repository.
API Reference
OpenLibraryClient
The main client class for interacting with the OpenLibrary API.
Constructor
new OpenLibraryClient(config?: OpenLibraryClientConfig)
Parameters:
config
(optional): Configuration options for the client
Configuration Options
interface OpenLibraryClientConfig {
baseURL?: string; // Default: 'https://openlibrary.org'
timeout?: number; // Default: 10000 (10 seconds)
headers?: Record<string, string>; // Custom headers
}
Methods
searchBooks(params: BookSearchParams)
Search for books using the OpenLibrary search API.
Parameters:
interface BookSearchParams {
q: string; // Main search query (required)
title?: string; // Search by title
author?: string; // Search by author
isbn?: string; // Search by ISBN
subject?: string; // Search by subject
limit?: number; // Number of results (default: 10, max: 100)
offset?: number; // Pagination offset (default: 0)
fields?: string; // Specific fields to include
lang?: string; // Language preference (e.g., 'en', 'fr', 'es')
first_publish_year?: number | YearRange; // Filter by first publication year or range
publish_year?: number | YearRange; // Filter by any publication year or range
sort?: SortOption; // Sort results by various criteria
}
interface YearRange {
start: number; // Start year (inclusive)
end: number; // End year (inclusive)
}
type SortOption = 'random' | 'new' | 'old' | 'rating' | 'title' | 'relevance';
Returns:
Promise<ApiResponse<BookSearchResponse>>
getWork(workKey: string)
Get detailed information about a specific work.
Parameters:
workKey
: The OpenLibrary work key (e.g., "OL45804W")
Returns:
Promise<ApiResponse<WorkDetails>>
getEdition(editionKey: string)
Get detailed information about a specific edition.
Parameters:
editionKey
: The OpenLibrary edition key (e.g., "OL7353617M")
Returns:
Promise<ApiResponse<EditionDetails>>
getBookByISBN(isbn: string)
Get book information by ISBN.
Parameters:
isbn
: The ISBN (10 or 13 digits)
Returns:
Promise<ApiResponse<BookDetails>>
getCoverUrl(coverId: number, size?: 'S' | 'M' | 'L')
Generate cover image URL from cover ID.
Parameters:
coverId
: The cover ID numbersize
: Size of the cover image (default: 'M')
Returns: Cover image URL string
getCoverUrlByISBN(isbn: string, size?: 'S' | 'M' | 'L')
Generate cover image URL from ISBN.
Parameters:
isbn
: The ISBN (10 or 13 digits)size
: Size of the cover image (default: 'M')
Returns: Cover image URL string
Example:
// Basic search with type safety
const basicParams: BookSearchParams = {
q: 'javascript programming'
};
const results = await client.searchBooks(basicParams);
// Advanced search with multiple parameters
const advancedParams: BookSearchParams = {
q: 'programming',
subject: 'javascript',
limit: 20,
offset: 0,
lang: 'en',
fields: 'key,title,author_name,first_publish_year,isbn'
};
const results = await client.searchBooks(advancedParams);
// Search by specific criteria
const authorParams: BookSearchParams = {
q: '*',
author: 'Douglas Crockford',
title: 'JavaScript'
};
const results = await client.searchBooks(authorParams);
// Random book search with advanced filtering
const randomSciFiParams: BookSearchParams = {
q: '*',
subject: 'science fiction',
first_publish_year: { start: 1980, end: 1989 }, // Books from the 1980s
sort: 'random',
limit: 5
};
const randomBooks = await client.searchBooks(randomSciFiParams);
// Random book in specific language
const randomFrenchParams: BookSearchParams = {
q: '*',
lang: 'fr',
sort: 'random',
limit: 3
};
const frenchBooks = await client.searchBooks(randomFrenchParams);
// Sort by different criteria
const recentBooksParams: BookSearchParams = {
q: 'programming',
subject: 'computers',
sort: 'new',
limit: 10
};
const recentBooks = await client.searchBooks(recentBooksParams);
// Get detailed work information
const workDetails = await client.getWork("OL45804W");
console.log(workDetails.data.title);
console.log(workDetails.data.description);
// Get specific edition details
const editionDetails = await client.getEdition("OL7353617M");
console.log(editionDetails.data.title);
console.log(editionDetails.data.number_of_pages);
// Get book by ISBN
const bookDetails = await client.getBookByISBN("9780547928227");
console.log(bookDetails.data.title);
console.log(bookDetails.data.publishers);
// Generate cover URLs
const coverUrl = client.getCoverUrl(8739161, 'M');
const coverUrlByISBN = client.getCoverUrlByISBN('9780547928227', 'L');
Response Types
BookSearchResponse
interface BookSearchResponse {
numFound: number; // Total number of results found
start: number; // Starting position
numFoundExact: boolean; // Whether count is exact
docs: BookSearchResult[]; // Array of book results
num_found: number; // Alternative count field
q: string; // Original query
offset: number | null; // Current offset
}
BookSearchResult
Each book result contains detailed information:
interface BookSearchResult {
key: string; // OpenLibrary work key
title: string; // Book title
author_name?: string[]; // Author names
author_key?: string[]; // Author keys
first_publish_year?: number; // First publication year
publish_year?: number[]; // All publication years
isbn?: string[]; // ISBN numbers
publisher?: string[]; // Publishers
subject?: string[]; // Subjects/topics
cover_i?: number; // Cover image ID
edition_count: number; // Number of editions
has_fulltext: boolean; // Full text available
// ... and many more fields
}
WorkDetails
Detailed work information:
interface WorkDetails {
key: string; // Work key
title: string; // Work title
description?: string | object; // Work description
authors?: Array<object>; // Author information
subjects?: string[]; // Subject classifications
covers?: number[]; // Cover image IDs
first_publish_date?: string; // First publication date
links?: Array<object>; // External links
// ... and more metadata
}
EditionDetails
Detailed edition information:
interface EditionDetails {
key: string; // Edition key
title: string; // Edition title
subtitle?: string; // Subtitle
authors?: Array<object>; // Author references
works?: Array<object>; // Work references
isbn_10?: string[]; // ISBN-10 numbers
isbn_13?: string[]; // ISBN-13 numbers
publishers?: string[]; // Publishers
publish_date?: string; // Publication date
number_of_pages?: number; // Page count
physical_format?: string; // Format (hardcover, paperback, etc.)
covers?: number[]; // Cover image IDs
// ... and more edition-specific data
}
BookDetails
Book information (from ISBN lookup):
interface BookDetails {
key: string; // Book key
title: string; // Book title
subtitle?: string; // Subtitle
description?: string | object; // Description
authors?: Array<object>; // Author information
publishers?: string[]; // Publishers
publish_date?: string; // Publication date
isbn_10?: string[]; // ISBN-10 numbers
isbn_13?: string[]; // ISBN-13 numbers
number_of_pages?: number; // Page count
covers?: number[]; // Cover image IDs
subjects?: string[]; // Subjects
// ... and more book data
}
Error Handling
The client provides structured error handling with TypeScript support:
import { ApiError } from 'open-library-client';
try {
const searchParams: BookSearchParams = { q: 'test' };
const results = await client.searchBooks(searchParams);
} catch (error) {
const apiError = error as ApiError;
if (apiError.status) {
console.error(`API Error ${apiError.status}: ${apiError.message}`);
} else {
console.error(`Network Error: ${apiError.message}`);
}
}
Random Book Discovery
The client supports advanced filtering and random sorting for discovering books by various criteria:
Random Books by Genre and Year
// Get random science fiction books from the 1980s
const randomSciFi: BookSearchParams = {
q: '*',
subject: 'science fiction',
first_publish_year: { start: 1980, end: 1989 },
sort: 'random',
limit: 5
};
const sciFiBooks = await client.searchBooks(randomSciFi);
Random Books by Language
// Get random books in French
const randomFrench: BookSearchParams = {
q: '*',
lang: 'fr',
sort: 'random',
limit: 5
};
const frenchBooks = await client.searchBooks(randomFrench);
Sorting Options
// Sort by newest first
const newestBooks: BookSearchParams = {
q: 'artificial intelligence',
sort: 'new',
limit: 10
};
// Sort by highest rated
const topRated: BookSearchParams = {
q: 'machine learning',
sort: 'rating',
limit: 10
};
// Sort alphabetically by title
const alphabetical: BookSearchParams = {
q: 'data science',
sort: 'title',
limit: 10
};
Advanced Usage
Custom Configuration
const client = new OpenLibraryClient({
timeout: 15000,
headers: {
'User-Agent': 'MyApp/1.0.0'
}
});
Working with Results
const searchParams: BookSearchParams = {
q: 'artificial intelligence',
limit: 10
};
const results: ApiResponse<BookSearchResponse> = await client.searchBooks(searchParams);
// Access metadata with full type safety
console.log(`Total results: ${results.data.numFound}`);
console.log(`Showing: ${results.data.docs.length} books`);
console.log(`Response status: ${results.status} ${results.statusText}`);
// Process each book with TypeScript autocompletion
results.data.docs.forEach((book, index) => {
console.log(`${index + 1}. ${book.title}`);
if (book.author_name?.length) {
console.log(` Authors: ${book.author_name.join(', ')}`);
}
if (book.first_publish_year) {
console.log(` First published: ${book.first_publish_year}`);
}
if (book.cover_i) {
const coverUrl = `https://covers.openlibrary.org/b/id/${book.cover_i}-M.jpg`;
console.log(` Cover: ${coverUrl}`);
}
if (book.isbn?.length) {
console.log(` ISBN: ${book.isbn[0]}`);
}
});
Pagination
// Get first page with typed parameters
const baseParams: BookSearchParams = {
q: 'science fiction',
limit: 10,
offset: 0
};
let results: ApiResponse<BookSearchResponse> = await client.searchBooks(baseParams);
console.log(`Page 1: ${results.data.docs.length} results`);
// Get second page using spread operator for type safety
const nextPageParams: BookSearchParams = {
...baseParams,
offset: 10
};
results = await client.searchBooks(nextPageParams);
console.log(`Page 2: ${results.data.docs.length} results`);
Development Roadmap
✅ Completed Features:
- Book Search: Complete search functionality with advanced filtering
- Work Details: Get detailed information about specific works
- Edition Data: Access specific edition information
- Random Discovery: Random book selection with genre, year, and language filtering
- Cover Images: Generate cover image URLs from cover IDs and ISBNs
- ISBN Lookup: Direct book lookup by ISBN-10 or ISBN-13
🚧 Future Enhancements:
- Author Information: Retrieve author details and bibliographies
- Subject Browsing: Browse books by subject categories
- Reading Lists: Integration with OpenLibrary reading lists
- Rate Limiting: Built-in rate limiting for API compliance
- Caching: Optional response caching for better performance
- Batch Operations: Support for batch requests
Contributing
This is an open-source project and contributions are welcome! Please see our contributing guidelines for more information.
License
MIT License - see LICENSE file for details.
Links
Built with ❤️ for the JavaScript and TypeScript community.