UNPKG

bgg-xml-api-client

Version:

A client for Boardgamegeek.com XML API (v1 and v2) that returns data as JS object.

209 lines (189 loc) 7.02 kB
'use strict'; const ofetch = require('ofetch'); const fastXmlParser = require('fast-xml-parser'); function createResourceUrl(resource, queryParams) { if (!resource) throw new Error("You have to provide valid resource name!"); const isV1Api = /geeklist/i.test(resource); if (isV1Api) { const query = queryParams.comments ? `?comments=${queryParams.comments}` : ""; return `${resource}/${queryParams.id}${query}`; } return `${resource}${queryParams && Object.keys(queryParams).length ? `?${new URLSearchParams(queryParams)}` : ""}`; } const options = { allowBooleanAttributes: true, attributeNamePrefix: "", ignoreAttributes: false, ignoreDeclaration: true, parseAttributeValue: true, textNodeName: "text" }; const parser = new fastXmlParser.XMLParser(options); const xmlParser = { parse: (xmlString) => parser.parse(xmlString) }; const BGG_API_V1_BASE_URL = "https://boardgamegeek.com/xmlapi/"; const BGG_API_V2_BASE_URL = "https://boardgamegeek.com/xmlapi2/"; function getBaseUrlForResource(resource) { if (!resource) throw new Error("You have to provide valid resource name!"); return resource === "geeklist" ? BGG_API_V1_BASE_URL : BGG_API_V2_BASE_URL; } const DEFAULT_MAX_RETRIES = 10; const DEFAULT_INTERVAL = 5e3; const DEFAULT_TIMEOUT = 1e4; const bggXmlApiClient = { get: async (resource, queryParams, { authorizationKey, maxRetries = DEFAULT_MAX_RETRIES, retryInterval = DEFAULT_INTERVAL, timeout = DEFAULT_TIMEOUT }) => { if (!authorizationKey) { throw new Error("authorizationKey is required to access BGG API as of fall 2025. See README for more details."); } const apiFetch = ofetch.ofetch.create({ baseURL: getBaseUrlForResource(resource), headers: { "Content-Type": "text/xml", "Authorization": `Bearer ${authorizationKey}` }, responseType: "text", onResponse(context) { if (context.response.status === 202) throw new Error("processing..."); } }); for (let i = 0; i < maxRetries; i++) { try { const resourceUrl = createResourceUrl(resource, queryParams); const response = await apiFetch(resourceUrl, { timeout }); const parsedResponse = xmlParser.parse(response); return parsedResponse[Object.keys(parsedResponse).shift()]; } catch (err) { if (err instanceof Error && err.message === "processing...") await new Promise((resolve) => setTimeout(() => resolve(), retryInterval)); else throw err; } } throw new Error(`Max retries reached! Resource: ${resource}, Params: ${JSON.stringify(queryParams)}`); } }; const bggXmlApiClient$1 = bggXmlApiClient; function getBggCollection(params, settings) { const newParams = { ...params, ...params.id && { id: Array.isArray(params.id) ? params.id.join(",") : params.id } }; return bggXmlApiClient.get("collection", newParams, settings); } function getBggFamily(params, settings) { const newParams = { ...params, ...params.id && { id: Array.isArray(params.id) ? params.id.join(",") : params.id } }; return bggXmlApiClient.get("family", newParams, settings); } function getBggForum(params, settings) { return bggXmlApiClient.get("forum", params, settings); } function getBggForumlist(params, settings) { return bggXmlApiClient.get("forumlist", params, settings); } function getBggGeeklist(params, settings) { return bggXmlApiClient$1.get("geeklist", params, settings); } function getBggGuild(params, settings) { return bggXmlApiClient.get("guild", params, settings); } function getBggHot(params, settings) { return bggXmlApiClient.get("hot", params, settings); } function getBggPlays(params, settings) { if (!params.username && !(params.id && params.type)) throw new Error("You must specify either username or id and type"); return bggXmlApiClient.get("plays", params, settings); } function getBggSearch(params, settings) { const newParams = { ...params, ...params.type && { type: Array.isArray(params.type) ? params.type.join(",") : params.type } }; return bggXmlApiClient.get("search", newParams, settings); } function getBggThing(params, settings) { const newParams = { ...params, ...params.id && { id: Array.isArray(params.id) ? params.id.join(",") : params.id }, ...params.type && { type: Array.isArray(params.type) ? params.type.join(",") : params.type } }; return bggXmlApiClient.get("thing", newParams, settings); } function getBggThread(params, settings) { return bggXmlApiClient.get("thread", params, settings); } function getBggUser(params, settings) { return bggXmlApiClient$1.get("user", params, settings); } class BggXmlApiClient { constructor(bggApiToken) { this.bggApiToken = bggApiToken; } get(resource, queryParams, settings) { return bggXmlApiClient.get(resource, queryParams, { authorizationKey: this.bggApiToken, ...settings }); } getBggCollection(params, settings) { return getBggCollection(params, { authorizationKey: this.bggApiToken, ...settings }); } getBggFamily(params, settings) { return getBggFamily(params, { authorizationKey: this.bggApiToken, ...settings }); } getBggForum(params, settings) { return getBggForum(params, { authorizationKey: this.bggApiToken, ...settings }); } getBggForumlist(params, settings) { return getBggForumlist(params, { authorizationKey: this.bggApiToken, ...settings }); } getBggGeeklist(params, settings) { return getBggGeeklist(params, { authorizationKey: this.bggApiToken, ...settings }); } getBggGuild(params, settings) { return getBggGuild(params, { authorizationKey: this.bggApiToken, ...settings }); } getBggHot(params, settings) { return getBggHot(params, { authorizationKey: this.bggApiToken, ...settings }); } getBggPlays(params, settings) { return getBggPlays(params, { authorizationKey: this.bggApiToken, ...settings }); } getBggSearch(params, settings) { return getBggSearch(params, { authorizationKey: this.bggApiToken, ...settings }); } getBggThing(params, settings) { return getBggThing(params, { authorizationKey: this.bggApiToken, ...settings }); } getBggThread(params, settings) { return getBggThread(params, { authorizationKey: this.bggApiToken, ...settings }); } getBggUser(params, settings) { return getBggUser(params, { authorizationKey: this.bggApiToken, ...settings }); } } exports.BggXmlApiClient = BggXmlApiClient; exports.bggXmlApiClient = bggXmlApiClient; exports.getBggCollection = getBggCollection; exports.getBggFamily = getBggFamily; exports.getBggForum = getBggForum; exports.getBggForumlist = getBggForumlist; exports.getBggGeeklist = getBggGeeklist; exports.getBggGuild = getBggGuild; exports.getBggHot = getBggHot; exports.getBggPlays = getBggPlays; exports.getBggSearch = getBggSearch; exports.getBggThing = getBggThing; exports.getBggThread = getBggThread; exports.getBggUser = getBggUser;