UNPKG

@twurple/api

Version:

Interact with Twitch's API.

108 lines (107 loc) 5.05 kB
import { __decorate } from "tslib"; import { isNode } from '@d-fischer/detect-node'; import { createLogger } from '@d-fischer/logger'; import { PartitionedRateLimiter, PartitionedTimeBasedRateLimiter } from '@d-fischer/rate-limiter'; import { callTwitchApiRaw } from '@twurple/api-call'; import { extractUserId, rtfm } from '@twurple/common'; import { ConfigError } from "../errors/ConfigError.mjs"; import { HelixRateLimiter } from "../utils/HelixRateLimiter.mjs"; import { BaseApiClient } from "./BaseApiClient.mjs"; import { NoContextApiClient } from "./NoContextApiClient.mjs"; import { UserContextApiClient } from "./UserContextApiClient.mjs"; /** * An API client for the Twitch Helix API and other miscellaneous endpoints. * * @meta category main * @hideProtected */ let ApiClient = class ApiClient extends BaseApiClient { /** * Creates a new API client instance. * * @param config Configuration for the client instance. */ constructor(config) { if (!config.authProvider) { throw new ConfigError('No auth provider given. Please supply the `authProvider` option.'); } const rateLimitLoggerOptions = { name: 'twurple:api:rate-limiter', ...config.logger }; super(config, createLogger({ name: 'twurple:api:client', ...config.logger }), isNode ? new PartitionedRateLimiter({ getPartitionKey: req => { var _a; return (_a = req.userId) !== null && _a !== void 0 ? _a : null; }, createChild: () => new HelixRateLimiter({ logger: rateLimitLoggerOptions }), }) : new PartitionedTimeBasedRateLimiter({ logger: rateLimitLoggerOptions, bucketSize: 800, timeFrame: 64000, doRequest: async ({ options, clientId, accessToken, authorizationType, fetchOptions, mockServerPort, }) => await callTwitchApiRaw(options, clientId, accessToken, authorizationType, fetchOptions, mockServerPort), getPartitionKey: req => { var _a; return (_a = req.userId) !== null && _a !== void 0 ? _a : null; }, })); } /** * Creates a contextualized ApiClient that can be used to call the API in the context of a given user. * * @param user The user to use as context. * @param runner The callback to execute. * * A parameter is passed that should be used in place of the normal `ApiClient` * to ensure that all requests are executed in the given user's context. * * Please note that requests which require scope authorization ignore this context. * * The return value of your callback will be propagated to the return value of this method. */ async asUser(user, runner) { const ctx = new UserContextApiClient(this._config, this._logger, this._rateLimiter, extractUserId(user)); return await runner(ctx); } /** * Creates a contextualized ApiClient that can be used to call the API in the context of a given intent. * * @param intents A list of intents. The first one that is found in your auth provider will be used. * @param runner The callback to execute. * * A parameter is passed that should be used in place of the normal `ApiClient` * to ensure that all requests are executed in the given user's context. * * Please note that requests which require scope authorization ignore this context. * * The return value of your callback will be propagated to the return value of this method. */ async asIntent(intents, runner) { if (!this._authProvider.getAccessTokenForIntent) { throw new Error('Trying to use intents with an auth provider that does not support them'); } for (const intent of intents) { const user = await this._authProvider.getAccessTokenForIntent(intent); if (user) { const ctx = new UserContextApiClient(this._config, this._logger, this._rateLimiter, user.userId); return await runner(ctx); } } throw new Error(`Intents [${intents.join(', ')}] not found in auth provider`); } /** * Creates a contextualized ApiClient that can be used to call the API without the context of any user. * * This usually means that an app access token is used. * * @param runner The callback to execute. * * A parameter is passed that should be used in place of the normal `ApiClient` * to ensure that all requests are executed without user context. * * Please note that requests which require scope authorization ignore this context erasure. * * The return value of your callback will be propagated to the return value of this method. */ async withoutUser(runner) { const ctx = new NoContextApiClient(this._config, this._logger, this._rateLimiter); return await runner(ctx); } }; ApiClient = __decorate([ rtfm('api', 'ApiClient') ], ApiClient); export { ApiClient };