npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@libraree/uk-libraries-search

v1.1.4

Published

Search for books in any UK public library's catalogue and check availability at local branches.

Downloads

6

Readme

@libraree/uk-libraries-search

This package will allow you to:

  1. search for books in any UK public library's catalogue and check availability at local branches; and
  2. list other library-related reference data, such as the online catalogue's home page.

It is used to perform the back-end searches for Libraree.

This package will not work in Javascript front-ends because of CORS restrictions. The package's primary use-case is within a Node back-end or potentially within a browser extension (with URLs whitelisted in the extension manifest).

Delivery Approach

This package operates on a screen-scraping basis. As such, breakages can sometimes occur. The main causes of these are:

  1. A library service moves from one catalogue platform to another. This is the cause for breakages in the majority of cases;
  2. The catalogue platform itself is updated. This happens very occasionally.

To try and resolve such breakages as quickly as possible, all library services are tested once per week and any issues are rectified.

The successful operation of the package also depends on the availability of a library service's catalogue. If that goes down, this package won't be able to perform any searches and an exception will be thrown.

Basic Usage

Searching for a single book

const client = new Client();
const result = await client.searchBook('Wigan', '9780747532743');

The first parameter is either the name or code of a library service, as listed here. The second parameter is the ISBN of a book.

The result variable will look like this (when serialised):

{
    "service": "Wigan",
    "code": "E08000010",
    "isbn": "9780747532743",
    "url": "https://wigan.spydus.co.uk/cgi-bin/spydus.exe/ENQ/WPAC/BIBENQ?NRECS=1&ISBN=9780747532743",
    "id": "6933017",
    "availability": [
        {
            "branch": "Ashton-in-Makerfield Library",
            "available": 1,
            "unavailable": 0
        },
        {
            "branch": "Golborne Library",
            "available": 0,
            "unavailable": 1
        },
        {
            "branch": "Leigh Library",
            "available": 0,
            "unavailable": 1
        },
        {
            "branch": "Platt Bridge Library",
            "available": 1,
            "unavailable": 0
        },
        {
            "branch": "The Grange Community Library",
            "available": 1,
            "unavailable": 0
        }
    ]
}

The url value is the direct link to the book's listing in the library service's catalogue. The id value is the unique identifier for that book in the library service's catalogue.

Searching for multiple books

const client = new Client();
const results = await client.searchBooks('Wigan', [
        '9780747532743',
        '9780141036144',
        '9780141439518',
        '9781904271338',
        '9780007371464'
    ]);

The first parameter is either the name or code of a library service, as listed here. The second parameter is an array of ISBNs. The ISBNs might be editions of the same book, or completely different books altogether.

The results variable will contain an array of objects (each structured as above in the single book example).

Getting catalogue information about a specific library service

  const client = new Client();
  const result = client.getService('Wigan');

The result variable will look like this (when serialised):

{
    "name": "Wigan",
    "code": "E08000010",
    "type": "Spydus",
    "catalogueUrl": "https://wigan.spydus.co.uk/"
}

Listing all library services

  const client = new Client();
  const results = client.listServices();

The results variable will contain an array of objects (each structured as above in the specific library service example).

Listing a library service's branches

  const client = new Client();
  const result = await client.listLibraries('Wigan');

The result variable will look like this (when serialised):

{
    "name": "Wigan",
    "code": "E08000010",
    "branches": [
        "Ashton-in-Makerfield Library",
        "Aspull Library",
        "Atherton Library",
        "E Resources",
        "General Fiction Reserve Stock",
        "Golborne Library",
        "Hindley Library",
        "Ince Library",
        "Lamberhead Green Library",
        "Leigh Library",
        "Leigh Local History",
        "Marsh Green Library",
        "Platt Bridge Library",
        "Reserve Stock",
        "Schools Library Service",
        "Shevington Library",
        "Standish Library",
        "The Grange Community Library",
        "Tyldesley Library",
        "Wigan Library",
        "Wigan Local Studies"
    ]
}

Customising the HTTP requests

When instantiating a new Client instance, it's possible to pass in a custom HTTP agent implementation to deal with various scenarios such as proxies, custom headers, etc.

const client = new Client(httpClient);
const result = await client.listLibraries('Wigan');

The httpClient parameter must be a class which implements the IHttpClient interface and returns HttpResponse objects.

If no httpClient is provided, a default SuperAgent-based implementation is used.

Tests

This project is primarily driven by integration tests, however unit tests also exist to catch accidental bugs as quickly as possible during development.

  • Integration tests exercise every library service and genuinely communicate with their catalogues.
  • Unit tests exercise a low number of services per catalogue type. The tests use "canned" HTTP responses and don't actually communicate with catalogues.

Integration tests are scheduled to run as a GitHub Action once per week on a Friday. Any issues arising are typically dealt with over the following weekend, but on a best-efforts basis.

Unit tests use Proxyman log files to simulate HTTP traffic. These log files are based on earlier executions of the integration tests and are updated as and when required.

Known Issues

| Service | Type | Problem | Identified | | ----------------- | --------- | ------------------------------------------------------------ | ---------- | | Bexley | arenaV7 | LFR_SESSION_STATE cookie - JS-generated. | 23/08/2023 | | Halton | arenaV7 | Cloudflare prevents access (not a human). | 23/08/2023 | | Telford & Wrekin | arenaV7 | Ability to search by ISBN has been removed. | 23/08/2023 |

Acknowledgements

This library is an evolution of LibrariesHacked/catalogues-library by Dave Bathnes to which I was a contributor for some time. The main objective for creating this alternative package were:

  • using Typescript as the basis for development;
  • making unit testing of the package a possibility;
  • making code coverage monitoring a possibility; and
  • providing a search interface that was more consistent with Libraree's needs.

Generally speaking, the same functionality exists in this package with the exception of some of the optional "extras" of Catalogues-Library (e.g. LibraryThing search).

Much of the screen-scraping logic has been maintained, though logic branches that have been proven to be no longer required (via code coverage analysis during integration testing) have been pruned.