Skip to content

AaronWLChan/igdb-ts

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

igdb-ts

An unofficial TypeScript wrapper for v4 of IGDB.com API.

Install

npm i igdb-ts

Usage

Prerequisites

  • Obtain Client ID and Client Secret from Twitch.tv.
  • To obtain the above, follow instructions provided by IGDB here.
  • Assign authorized URLs. For development, add http://localhost.

Important Things to Note

  • You should treat your Client Secret like a password.
  • This package is intended for backend use only.
  • IGDB OAuth token limits. See here.
  • IGDB's notes on CORS.

Import

import { IGDB } from 'igdb-ts';

Instantiate & Initialise

  • CLIENT_ID - Client ID retrieved from Twitch
  • CLIENT_SECRET - Client Secret retrieved from Twitch
  • CLIENT_TOKEN - Twitch App Access Token (optional). You should pass this if you have a stored app access token.
  • onAccessTokenRetrieved
    • Callback for you to store your access token.
    • Passes clientToken and tokenExpiry (in milliseconds from Epoch).
    • Will not call on init() if given CLIENT_TOKEN
    • Will be called whenever your access token expires and will generate a new one for you automatically.
  • RATE_OPTIONS - Axio Rate Limit Options. Default settings are 4 requests / second as per IGDB documentation.
const CLIENT_ID = "MY_CLIENT_ID";
const CLIENT_SECRET = "MY_CLIENT_SECRET";
const CLIENT_TOKEN = "MY_CLIENT_TOKEN";
const RATE_OPTIONS = { maxRPS: 4 }

//Callback to save token to storage
const onAccessTokenRetrieved = (token: string, tokenExpiry: number) => {
	//Save to storage
}

const igdb = new IGDB();

igdb.init(CLIENT_ID, CLIENT_SECRET, CLIENT_TOKEN, onAccessTokenRetrieved, RATE_OPTIONS?);

Getting Data

Prebuilt Calls

All endpoints described in the API documentation are available. For example:

const games = await igdb.getGames();
const characters = await igdb.getCharacters()
Custom Calls

To build your own custom endpoint calls with your own typed response use the get<T>() function.

interface GameCount {
    count: number
}

//Get Game Count
const gameCount = await igdb.get<GameCount>("games/count");

Fields

By default all fields (*) are returned unless stated otherwise.

For Prebuilt Calls

Fields are typed based on the keys of each endpoint response.

import { SearchableIGDBOptions } from 'igdb-ts';

const options: SearchableIGDBOptions<Game> = {
	fields: ["name", "rating", "summary"]
}

const games = await igdb.getGames(options);
For Custom Calls

Fields do not have typing. It is recommended you use provided enums instead.

import { GameFields, GenreReferenceFields, UntypedIGDBOptions } from 'igdb-ts';

interface GameGenre {
    id: number,
    name: string
    rating: number,
    genres: { id: number, name: string }[]
}

const options: UntypedIGDBOptions = {
	fields: [GameFields.NAME, GameFields.RATING, GenreReferenceFields.NAME]
}

const games = await igdb.get<GameGenre[]>("games", options);

Exclude

For Prebuilt Calls

Exclude fields are typed.

import { SearchableIGDBOptions } from 'igdb-ts'

const options: SearchableIGDBOptions<Game> = {
	exclude: ["rating"]
}

const games = await igdb.getGames(options);
For Custom Calls

Exclude fields are not typed.

import { GameFields, UntypedIGDBOptions, Endpoints } from 'igdb-ts'

const options: UntypedIGDBOptions = {
	exclude: [GameFields.NAME]
}

const games = await igdb.get(Endpoints.GAME, options);

Expander

To use expanders, you must use the generic get() function as expanders will not follow the shape of defined endpoint response types.

To help build your expander calls use provided enums.

import { GameFields, GenreReferenceFields, UntypedIGDBOptions, Endpoints } from 'igdb-ts'

interface GameRatingGenre{
    id: number,
    name: string,
    rating: number,
    genres: { id: number, name; string }[]
}

const options: UntypedIGDBOptions = {
	fields: [GameFields.NAME, GameFields.RATING, GenreReferenceFields.NAME]
}

const games = await igdb.get<GameRatingGenre>(Endpoints.GAME, options);

Filters

Filters are not typed. This is because you can filter on expander fields e.g. platform.releaseDates.

Click here to view all available filter methods.

Use enums provided to ensure you are using correct fields.

import { GameFields, SearchableIGDBOptions } from 'igdb-ts';

const options: SearchableIGDBOptions<Game> = {
	filter: {
		filters: [
		    { GameFields.RATING, ">=", 80 },
	    	{ GameFields.PLATFORMS, "=", "[130, 48]" }
    	],
    	operators: ["&"]
	}
}


const games = await igdb.getGames(options);
Combined Filters

Combined filters are supported. Note: You cannot have a combinedFilter and filter at the same time.

import { Filter, SearchableIGDBOptions, GameFields } from 'igdb-ts'

// Games released for both PC (6), and PS4 (48) and also has the genre simulator (13).
const filter1: Filter = {
    filters: [
        { field: GameFields.PLATFORMS, postfix: "=", value: "[6, 48]" },
        { field: GameFields.GENRES, postfix: "=", value: 13 }
    ],
    operators: ["&"]
}

// Games released for both Switch (130), and PS4 (48) and also has the genre Role-Playing (13).
const filter2: Filter = {
    filters: [
        { field: GameFields.PLATFORMS, postfix: "=", value: "[130, 48]" },
        { field: GameFields.GENRES, postfix: "=", value: 12 }
    ],
    operators: ["&"]
}

const options: SearchableIGDBOptions<Game> = {
	combinedFilter: {
	    filters: [filter1, filter2],
	    operators: ["|"]
	}
}

const games = await igdb.getGames(options);

Sorting

Sorting fields are not typed as you can sort on expander fields. Use provided enums where possible.

import { GameFields, SearchableIGDBOptions } from 'igdb-ts';

const options: SearchableIGDBOptions<Game> = {
	sortBy: {
		field: GameFields.NAME,
		order: "asc"
	}
}

const games = await igdb.getGames(options);

Search

Searchable endpoints:

  • Characters
  • Collections
  • Games
  • People
  • Platforms
  • Themes
Prebuilt Calls

Prebuilt endpoint calls have been typed so you can only use search for the endpoints above.

//Will work
const games = await igdb.getGames({ search: "witcher" });

//Will show compiler error
const companies = await igdb.getCompanies({ search: "cd projekt" })
Custom Calls

Custom calls are not typed. Both will compile however, you will encounter an error response from IGDB for trying to search the Companies endpoint.

import { Endpoints } from 'igdb-ts';

//Will work
const games = await igdb.get(Endpoints.GAME, { search: "witcher" });

//Will work but will throw error when called
const companies = await igdb.get(Endpoints.COMPANY, { search: "cd projekt" })

Pagination

Provide an offset and limit.

import { SearchableIGDBOptions } from 'igdb-ts'

const options: SearchableIGDBOptions<Game> = {
	limit: 20,
	offset: 10,
}

const games = await igdb.getGames(options);

Multi-Query

Multiquery is supported. Return type is any[]. Therefore you will have to cast each query reponse yourself.

import { GameFields, PlatformReferenceFields, Query } from 'igdb-ts'

interface PlayStationGameResult {
    name: string,
    result: {
        id: number,
        name: string,
        platforms: { id: number, name: string }[]
    }
} 

interface PlatformCountResult {
    name: string,
    count: number
}

//Get PlayStation 4 Exclusives
const query1: Query = { 
	endpoint: "game",
	resultName: "PlayStation Games",
	options: {
		fields: [GameFields.NAME, PlatformReferenceFields.NAME],
		filter: {
		    filters: [
		        { GameFields.PLATFORM, "!=", null },
		        { GameFields.PLATFORM, "==", 48 }],
		        ],
		    operators: ["&"]
	    } 
	    limit: 1,
	}
};

//Get Count of Platforms
const query2: Query = { 
	endpoint: "platforms/count", 
	resultName: "Platform Count"
}

const multiQuery = await igdb.multiQuery([query1, query2]);

const playstationGames = multiQuery[0] as PlayStationGameResult
const platformCount = mulitQuery[1] as PlatformCountResult

Images

Image options can be found here.

import { ImageOptions } from 'igdb-ts'

const options: ImageOptions = {
	imageId:  "mnljdjtrh44x4snmierh",
	size:  "t_thumb",
	retina: true,
}

const imageUrl = igdb.getImageUrl(options);