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

gw2api-client

v7.8.3

Published

A javascript wrapper around the official Guild Wars 2 API

Downloads

478

Readme

gw2api-client

Build Status Coverage Status Greenkeeper badge Bundle Size

Javascript wrapper for the official Guild Wars 2 API.

Install

npm install gw2api-client

This module can be used for Node.js as well as browsers using Browserify.

Usage

Basic usage

const client = require('gw2api-client')

// Get an instance of an API client
let api = client()

// Optional, but recommended: Set the schema version of the client
api.schema('2019-03-26T00:00:00Z')

// Optional: Set the language of the client
api.language('en')

// Optional: Authenticate the client using an API key
api.authenticate('my-secret-key')

// Get the ids of all items
api.items().ids().then(items => console.log(items))

// Get a single item
api.items().get(123).then(item => console.log(item))

// Get multiple items
api.items().many([123, 456]).then(items => console.log(items))

// Get all items
api.items().all().then(items => console.log(items))

Endpoints

You can find all endpoints and their respective function calls in this document.

Caching

You can find all cache storages (and the interface for custom ones) in this document.

By default, calling any endpoint requests data from the live API. However, you can easily enable caching for all appropriate endpoints by giving the client a cache storage to work with. You can find the default cache times of all endpoints here.

const cacheMemory = require('gw2api-client/src/cache/memory')
api.cacheStorage(cacheMemory())

// This will only call the official API once
api.items().ids()
// ...
api.items().ids()

// When the cache expires, this will call the official API again
api.items().ids()

// You can skip the cache for guaranteed live data
api.items().live().ids()

Note: The cache storage save is asynchronous in the background. During this time, the API function already resolves a result for best performance. Therefore it can happen that some data gets requested twice, if you request it in rapid succession and are not using a cache that saves in memory (memory or browser caches).

You can also chain multiple cache storages together. In this case, the cache gets saved in all storages and read from the first storage in the list answering with a valid value. The more persistent and more reliable cache storages should therefore be on the end of the list and the fastest (e.g. memory) should be at the start of the list.

const cacheMemory = require('gw2api-client/src/cache/memory')
const cacheRedisStorage = require('gw2api-client/src/cache/redis')

// Save in memory and local storage
// Try to answer from memory first, then from local storage and then hit the API
api.cacheStorage([
  cacheMemory(),
  cacheRedisStorage({ ... })
])

The cache uses expiration times and not the build number, because the content of the API can update independently of the build id. This is caused by the internal whitelisting of the API. However, if you want your cache to invalidate when there is a game update, this is easily possible too:

// configure api.cacheStorage(...) beforehand

// Check the build every 10 minutes and flush the cache if it updated
setInterval(() => api.flushCacheIfGameUpdated(), 10 * 60 * 1000)

Error handling

You can use the Promise catch to handle all possible errors.

api.account().bank().catch(err => {
  // err.response is the last response object (e.g. err.response.status)
  // err.content is the parsed body of the response, if available
  // err.content.text is the error text thrown of the API, if available
  console.error('Something went wrong', err)
})

The API can throw server errors (status >= 500) that don't have a text property set. However, most of the time it responds with one of the following errors:

  • endpoint requires authentication
  • invalid key
  • requires scope <xyz>
  • membership required
  • access restricted to guild leaders
  • page out of range
  • no such id
  • all ids provided are invalid

Retrying

By accessing the fetch instance, you can enable retrying in case the API or the user has problems getting a valid response. You can find the full documentation for retrying here.

// Retry up to 3 times if the status indicates an request error
api.fetch.retry((tries, err) => {
  if (tries > 3) { 
    return false
  }

  const res = err.response
  if (res && (res.status < 400 || res.status === 403)) {
    return false
  }

  return true
})

// Wait in between retries
api.fetch.retryWait((tries) => tries * 100)

// This request will now retry if it fails (e.g. API issues)
api.items().ids()

Extending

You can extend or overwrite the API client with your own endpoints if you wish so. The only thing that is required is an extension of AbstractEndpoint to provide all the logic for pagination, bulk, localisation, caching and so on.

If you need more specific ways to handle data then the already defined ones, take a look at how the existing endpoints handle these edge cases (e.g. in /src/endpoints/recipes.js).

const client = require('gw2api-client')
const AbstractEndpoint = require('gw2api-client/src/endpoint')

// Get an instance of an API client
const api = client()

// Example: Add a new function inside the abstract endpoint
AbstractEndpoint.prototype.post = function () {
  console.log(this)
}

// Example: Define our custom "items" endpoint
class ItemsEndpoint extends AbstractEndpoint {
  constructor (client) {
    super(client)
    this.baseUrl = 'https://api.my-domain.com' // The base URL of the API
    this.url = '/items' // The endpoint URL path
    this.isPaginated = false // If the endpoint supports ?page and ?page_size
    this.isBulk = true // If the endpoint supports ?ids
    this.supportsBulkAll = false // If the endpoint supports ?ids=all
    this.isLocalized = true // If the endpoint supports ?lang
    this.cacheTime = 5 * 60 // How long to cache the endpoint responses for
    this.isAuthenticated = true // If the endpoint requires ?access_token

    this.credentials = true // If the endpoint requires credentials (e.g. session cookies)
  }
}

// Attach it to the client, either as a new endpoint or overwriting an already existing one
api.items = () => new ItemsEndpoint(api)

// Use the new, overwritten endpoint
api.items().many([123, 456])
  .then(items => console.log('Got the items', items))
  .catch(err => console.error('Things went badly', err))

Mocking

If you want to mock this module in your tests, you can replace the underlying lets-fetch library with the provided mock module, e.g. using rewire. You can find all available mock methods here.

const fetchMock = require('lets-fetch/mock')
const file = require('./some/file/using/gw2api/client.js')

// Get the variable "api" (which would be the initialized api client
// in your own code) and replace the fetch method with the fetchMock
file.__get__('api').fetch = fetchMock

// Use the fetch mock methods as described in the link above

Debugging

You can enable debug messages by setting a flag on the client:

const client = require('gw2api-client')
let api = client()

// Set for specific endpoints
let items = api.items().debugging(true).ids().then(items => console.log(items))

// Set for all endpoints
api.debugging(true).items().ids().then(items => console.log(items))

Tests

npm test

Licence

MIT