twitch-api-helix
Advanced tools
Comparing version 0.1.2 to 0.2.0
@@ -5,2 +5,14 @@ # Changelog | ||
## [0.2.0](https://github.com/AntoninJuquel/twitch-api-helix/compare/v0.1.2...v0.2.0) (2023-12-19) | ||
### ⚠ BREAKING CHANGES | ||
* some methods are moved under some components and are no longer available at the | ||
root class | ||
### Features | ||
* overhaul usage of composition and doc update ([0418b4f](https://github.com/AntoninJuquel/twitch-api-helix/commit/0418b4f365ab50420e4a39c2c81207582ab7b21d)) | ||
### [0.1.2](https://github.com/AntoninJuquel/twitch-api-helix/compare/v0.1.1...v0.1.2) (2023-12-18) | ||
@@ -7,0 +19,0 @@ |
@@ -6,1 +6,2 @@ export declare const API_PREFIX = "https://api.twitch.tv/helix"; | ||
export declare const VALIDATE_TOKEN_ENDPOINT: string; | ||
export declare const twitchAxios: import("axios").AxiosInstance; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.VALIDATE_TOKEN_ENDPOINT = exports.ACCESS_TOKEN_ENDPOINT = exports.AUTHORIZATION_ENDPOINT = exports.OAUTH2_PREFIX = exports.API_PREFIX = void 0; | ||
exports.API_PREFIX = 'https://api.twitch.tv/helix'; | ||
exports.OAUTH2_PREFIX = 'https://id.twitch.tv/oauth2'; | ||
exports.twitchAxios = exports.VALIDATE_TOKEN_ENDPOINT = exports.ACCESS_TOKEN_ENDPOINT = exports.AUTHORIZATION_ENDPOINT = exports.OAUTH2_PREFIX = exports.API_PREFIX = void 0; | ||
const axios_1 = require("axios"); | ||
exports.API_PREFIX = "https://api.twitch.tv/helix"; | ||
exports.OAUTH2_PREFIX = "https://id.twitch.tv/oauth2"; | ||
exports.AUTHORIZATION_ENDPOINT = `${exports.OAUTH2_PREFIX}/authorize`; | ||
exports.ACCESS_TOKEN_ENDPOINT = `${exports.OAUTH2_PREFIX}/token`; | ||
exports.VALIDATE_TOKEN_ENDPOINT = `${exports.OAUTH2_PREFIX}/validate`; | ||
exports.twitchAxios = axios_1.default.create({ | ||
baseURL: exports.API_PREFIX, | ||
headers: { | ||
"Client-ID": process.env.TWITCH_CLIENT_ID, | ||
Authorization: `Bearer ${process.env.TWITCH_ACCESS_TOKEN}`, | ||
}, | ||
}); |
@@ -1,46 +0,3 @@ | ||
import { GenericTwitchResponse, TwitchClipRequestParams, TwitchGame, TwitchUser, TwitchClip, OAuth2ValidateTokenResponseBody, OAuth2TokenResponseBody } from "./types"; | ||
declare const Twitch: typeof import("./classes/twitch").default, Users: typeof import("./classes/users").default, Games: typeof import("./classes/games").default, Clips: typeof import("./classes/clips").default, Authentication: typeof import("./classes/authentication").default; | ||
export { Twitch as default, Twitch, Users, Games, Clips, Authentication }; | ||
export * from "./types"; | ||
export default class Twitch { | ||
private twitch; | ||
private clientId; | ||
private clientSecret; | ||
constructor(clientId: string, clientSecret: string); | ||
refreshToken(): Promise<import("axios").AxiosResponse<OAuth2TokenResponseBody, any>>; | ||
validateToken(): Promise<import("axios").AxiosResponse<OAuth2ValidateTokenResponseBody, any>>; | ||
get getClientId(): string; | ||
get getClientSecret(): string; | ||
/** | ||
* Set the client ID for the Twitch API | ||
* @param clientId Client ID | ||
*/ | ||
setClientId(clientId: string): void; | ||
/** | ||
* Set the client secret for the Twitch API | ||
* @param clientSecret Client secret | ||
*/ | ||
setClientSecret(clientSecret: string): void; | ||
/** | ||
* Set the client ID and client secret for the Twitch API | ||
* @param clientId Client ID | ||
* @param clientSecret Client secret | ||
* @returns Promise<{ message: string }> | ||
* @throws Error if request failed | ||
* @throws Error if client ID or client secret is invalid | ||
* @throws Error if token refresh failed | ||
* @throws Error if token validation failed | ||
*/ | ||
setCredentials(clientId: string, clientSecret: string): Promise<import("axios").AxiosResponse<OAuth2TokenResponseBody, any>>; | ||
/** | ||
* Generic GET request to the Twitch API | ||
* @doc https://dev.twitch.tv/docs/api/reference/ | ||
* @param endpoint Endpoint to request | ||
* @param params Query parameters | ||
* @returns GenericTwitchResponse<T> | ||
* @throws Error if request failed | ||
*/ | ||
get<T>(endpoint: string, params: Record<string, string | number>): Promise<GenericTwitchResponse<T>>; | ||
getById<T>(endpoint: string, id: string): Promise<T[]>; | ||
getGameByName(name: string): Promise<TwitchGame[]>; | ||
getUserByName(name: string): Promise<TwitchUser[]>; | ||
getClips(params: TwitchClipRequestParams): Promise<GenericTwitchResponse<TwitchClip>>; | ||
} |
@@ -16,167 +16,12 @@ "use strict"; | ||
}; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const axios_1 = require("axios"); | ||
const globals_1 = require("./globals"); | ||
exports.Authentication = exports.Clips = exports.Games = exports.Users = exports.Twitch = exports.default = void 0; | ||
const classes_1 = require("./classes"); | ||
const { Twitch, Users, Games, Clips, Authentication } = classes_1.default; | ||
exports.default = Twitch; | ||
exports.Twitch = Twitch; | ||
exports.Users = Users; | ||
exports.Games = Games; | ||
exports.Clips = Clips; | ||
exports.Authentication = Authentication; | ||
__exportStar(require("./types"), exports); | ||
class Twitch { | ||
constructor(clientId, clientSecret) { | ||
this.clientId = clientId; | ||
this.clientSecret = clientSecret; | ||
this.twitch = axios_1.default.create({ | ||
baseURL: globals_1.API_PREFIX, | ||
headers: { | ||
"Client-ID": this.clientId, | ||
}, | ||
}); | ||
this.twitch.interceptors.response.use((response) => response, (error) => __awaiter(this, void 0, void 0, function* () { | ||
var _a, _b, _c, _d; | ||
if (((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 401 && error.config) { | ||
yield this.refreshToken(); | ||
return this.twitch.request(error.config); | ||
} | ||
throw new Error((_d = (_c = (_b = error.response) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.message) !== null && _d !== void 0 ? _d : error.message); | ||
})); | ||
} | ||
refreshToken() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const response = yield axios_1.default | ||
.post(globals_1.ACCESS_TOKEN_ENDPOINT, { | ||
client_id: this.clientId, | ||
client_secret: this.clientSecret, | ||
grant_type: "client_credentials", | ||
}) | ||
.then((res) => { | ||
const { access_token: accessToken } = res.data; | ||
this.twitch.defaults.headers.Authorization = `Bearer ${accessToken}`; | ||
return res; | ||
}) | ||
.catch((err) => { | ||
var _a, _b, _c; | ||
throw new Error((_c = (_b = (_a = err.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.message) !== null && _c !== void 0 ? _c : err.message); | ||
}); | ||
return response; | ||
}); | ||
} | ||
validateToken() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this.twitch.defaults.headers.Authorization === undefined) { | ||
yield this.refreshToken(); | ||
} | ||
const response = yield axios_1.default | ||
.get(globals_1.VALIDATE_TOKEN_ENDPOINT, { | ||
headers: { | ||
Authorization: this.twitch.defaults.headers.Authorization, | ||
}, | ||
}) | ||
.catch((err) => { | ||
var _a, _b, _c; | ||
throw new Error((_c = (_b = (_a = err.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.message) !== null && _c !== void 0 ? _c : err.message); | ||
}); | ||
return response; | ||
}); | ||
} | ||
get getClientId() { | ||
return this.clientId; | ||
} | ||
get getClientSecret() { | ||
return this.clientSecret; | ||
} | ||
/** | ||
* Set the client ID for the Twitch API | ||
* @param clientId Client ID | ||
*/ | ||
setClientId(clientId) { | ||
this.clientId = clientId; | ||
this.twitch.defaults.headers["Client-ID"] = clientId; | ||
} | ||
/** | ||
* Set the client secret for the Twitch API | ||
* @param clientSecret Client secret | ||
*/ | ||
setClientSecret(clientSecret) { | ||
this.clientSecret = clientSecret; | ||
} | ||
/** | ||
* Set the client ID and client secret for the Twitch API | ||
* @param clientId Client ID | ||
* @param clientSecret Client secret | ||
* @returns Promise<{ message: string }> | ||
* @throws Error if request failed | ||
* @throws Error if client ID or client secret is invalid | ||
* @throws Error if token refresh failed | ||
* @throws Error if token validation failed | ||
*/ | ||
setCredentials(clientId, clientSecret) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this.setClientId(clientId); | ||
this.setClientSecret(clientSecret); | ||
const response = yield this.refreshToken(); | ||
return response; | ||
}); | ||
} | ||
/** | ||
* Generic GET request to the Twitch API | ||
* @doc https://dev.twitch.tv/docs/api/reference/ | ||
* @param endpoint Endpoint to request | ||
* @param params Query parameters | ||
* @returns GenericTwitchResponse<T> | ||
* @throws Error if request failed | ||
*/ | ||
get(endpoint, params) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const response = yield this.twitch | ||
.get(endpoint, { | ||
params, | ||
}) | ||
.then((res) => { | ||
if (res.data.data.length === 0) | ||
throw new Error(`No data found for ${endpoint} with params | ||
${JSON.stringify(params, null, 2)}`); | ||
return res.data; | ||
}) | ||
.catch((err) => { | ||
var _a, _b, _c; | ||
throw new Error((_c = (_b = (_a = err.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.message) !== null && _c !== void 0 ? _c : err.message); | ||
}); | ||
return response; | ||
}); | ||
} | ||
getById(endpoint, id) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const response = yield this.get(endpoint, { id }); | ||
return response.data; | ||
}); | ||
} | ||
getGameByName(name) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const response = yield this.get("games", { | ||
name, | ||
}); | ||
return response.data; | ||
}); | ||
} | ||
getUserByName(name) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const response = yield this.get("users", { | ||
login: name, | ||
}); | ||
return response.data; | ||
}); | ||
} | ||
getClips(params) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const response = yield this.get("clips", params); | ||
return response; | ||
}); | ||
} | ||
} | ||
exports.default = Twitch; |
/** | ||
* https://dev.twitch.tv/docs/authentication/getting-tokens-oauth | ||
*/ | ||
export type OAuth2Init = { | ||
clientId: string; | ||
clientSecret: string; | ||
}; | ||
/** | ||
* https://dev.twitch.tv/docs/api/reference | ||
@@ -24,25 +17,1 @@ */ | ||
}; | ||
/** | ||
* https://dev.twitch.tv/docs/api/reference/#get-users | ||
*/ | ||
export type TwitchUser = { | ||
id: string; | ||
login: string; | ||
display_name: string; | ||
type: string; | ||
broadcaster_type: string; | ||
description: string; | ||
profile_image_url: string; | ||
offline_image_url: string; | ||
email: string; | ||
created_at: string; | ||
}; | ||
/** | ||
* https://dev.twitch.tv/docs/api/reference/#get-games | ||
*/ | ||
export type TwitchGame = { | ||
id: string; | ||
name: string; | ||
box_art_url: string; | ||
igdb_id: string; | ||
}; |
export * from './oauth2'; | ||
export * from './client'; | ||
export * from './clip'; | ||
export * from './clips'; | ||
export * from './games'; | ||
export * from './users'; |
@@ -19,2 +19,4 @@ "use strict"; | ||
__exportStar(require("./client"), exports); | ||
__exportStar(require("./clip"), exports); | ||
__exportStar(require("./clips"), exports); | ||
__exportStar(require("./games"), exports); | ||
__exportStar(require("./users"), exports); |
@@ -13,3 +13,3 @@ { | ||
}, | ||
"version": "0.1.2", | ||
"version": "0.2.0", | ||
"main": "dist/index.js", | ||
@@ -16,0 +16,0 @@ "types": "dist/index.d.ts", |
242
README.md
@@ -6,6 +6,4 @@ # TWITCH API HELIX | ||
## Description | ||
This is a simple module to interact with Twitch Helix API. Fully written in TypeScript. | ||
This is a simple module to interact with Twitch Helix API. | ||
## Installation | ||
@@ -16,15 +14,241 @@ | ||
``` | ||
```sh | ||
yarn add twitch-api-helix | ||
``` | ||
Then you **must** [Register your Twitch application](https://dev.twitch.tv/docs/api/get-started/#register-an-application) to get your `CLIENT_ID` and `CLIENT_SECRET`, the package will take care of the OAuth2 process. | ||
You will just need to provide the `CLIENT_ID` and `CLIENT_SECRET` to the constructor, feel free to store them in a `.env` file. | ||
Feeld free to check the [Twitch Helix API Reference](https://dev.twitch.tv/docs/api/reference) for more information. | ||
## Usage | ||
```javascript | ||
import TwitchApi from 'twitch-api-helix'; | ||
```js | ||
import TwitchApi from "twitch-api-helix"; | ||
const twitch = new TwitchApi(CLIENT_ID, CLIENT_SECRET); | ||
const twitchApi = new TwitchApi( | ||
process.env.CLIENT_ID, | ||
process.env.CLIENT_SECRET | ||
); | ||
``` | ||
twitch.getGameByName("League of Legends").then((game) => { | ||
console.log(game); | ||
## API | ||
### [Authentication](github.com/AntoninJuquel/twitch-api-helix/blob/master/lib/classes/authentication.ts) | ||
#### refreshAccessToken() | ||
Refresh the access token, you can call this method manually but it will be called automatically when a request is made and the access token is expired. | ||
```js | ||
twitchApi.authentication.refreshAccessToken(); | ||
``` | ||
#### validateAccessToken() | ||
Validate the access token, if it is valid nothing will happen, if it is not valid it will be refreshed. | ||
```js | ||
twitchApi.authentication.validateAccessToken(); | ||
``` | ||
### [Clips](github.com/AntoninJuquel/twitch-api-helix/blob/master/lib/classes/clips.ts) | ||
#### getClips(TwitchClipsRequestParams) => TwitchClipsResponseBody | ||
```ts | ||
type TwitchClipsRequestParams = ( | ||
| { | ||
broadcaster_id: string; | ||
} | ||
| { | ||
game_id: string; | ||
} | ||
| { | ||
id: string; | ||
} | ||
) & { | ||
first?: number; | ||
started_at?: string; | ||
ended_at?: string; | ||
after?: string; | ||
before?: string; | ||
}; | ||
``` | ||
```ts | ||
type TwitchClipsResponseBody = { | ||
data: TwitchClip[]; | ||
pagination?: | ||
| { | ||
cursor: string; | ||
} | ||
| undefined; | ||
}; | ||
``` | ||
```ts | ||
type TwitchClip = { | ||
id: string; | ||
url: string; | ||
embed_url: string; | ||
broadcaster_id: string; | ||
broadcaster_name: string; | ||
creator_id: string; | ||
creator_name: string; | ||
video_id: string; | ||
game_id: string; | ||
language: string; | ||
title: string; | ||
view_count: number; | ||
created_at: string; | ||
thumbnail_url: string; | ||
duration: number; | ||
vod_offset: number; | ||
}; | ||
``` | ||
Get clips by ID. | ||
```js | ||
twitchApi.clips.getClips({ | ||
id: "123456789", | ||
}); | ||
``` | ||
``` | ||
Get clips by broadcaster ID | ||
```js | ||
twitchApi.clips.getClips({ | ||
broadcaster_id: "123456789", | ||
first: 10, | ||
}); | ||
``` | ||
Get clips by game ID | ||
```js | ||
twitchApi.clips.getClips({ | ||
game_id: "123456789", | ||
first: 10, | ||
}); | ||
``` | ||
### [Games](github.com/AntoninJuquel/twitch-api-helix/blob/master/lib/classes/games.ts) | ||
#### getGame(TwitchGamesRequestParams) => TwitchGamesResponseBody | ||
```ts | ||
type TwitchGamesRequestParams = | ||
| { | ||
id: string; | ||
} | ||
| { | ||
name: string; | ||
} | ||
| { | ||
igdb_id: string; | ||
}; | ||
``` | ||
```ts | ||
type TwitchGamesResponseBody = { | ||
data: TwitchGame[]; | ||
pagination?: | ||
| { | ||
cursor: string; | ||
} | ||
| undefined; | ||
}; | ||
``` | ||
```ts | ||
type TwitchGame = { | ||
id: string; | ||
name: string; | ||
box_art_url: string; | ||
igdb_id?: number; | ||
}; | ||
``` | ||
Get games by ID. | ||
```js | ||
twitchApi.games.getGame({ | ||
id: "123456789", | ||
}); | ||
``` | ||
Get games by name. | ||
```js | ||
twitchApi.games.getGame({ | ||
name: "Fortnite", | ||
}); | ||
``` | ||
Get games by IGDB ID. | ||
```js | ||
twitchApi.games.getGame({ | ||
igdb_id: "123456789", | ||
}); | ||
``` | ||
### [Users](github.com/AntoninJuquel/twitch-api-helix/blob/master/lib/classes/users.ts) | ||
#### getUser(TwitchUsersRequestParams) => TwitchUsersResponseBody | ||
```ts | ||
type TwitchUsersRequestParams = | ||
| { | ||
id: string; | ||
} | ||
| { | ||
login: string; | ||
}; | ||
``` | ||
```ts | ||
type TwitchUsersResponseBody = { | ||
data: TwitchUser[]; | ||
pagination?: | ||
| { | ||
cursor: string; | ||
} | ||
| undefined; | ||
}; | ||
``` | ||
```ts | ||
type TwitchUser = { | ||
id: string; | ||
login: string; | ||
display_name: string; | ||
type: string; | ||
broadcaster_type: string; | ||
description: string; | ||
profile_image_url: string; | ||
offline_image_url: string; | ||
email: string; | ||
created_at: string; | ||
}; | ||
``` | ||
Get users by ID. | ||
```js | ||
twitchApi.users.getUser({ | ||
id: "123456789", | ||
}); | ||
``` | ||
Get users by login. | ||
```js | ||
twitchApi.users.getUser({ | ||
login: "Somindras", | ||
}); | ||
``` |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
34697
33
681
253
2
1