// Copyright (c) Tribufu. All Rights Reserved. import { HttpHeaders, HttpClient } from "@tribufu/mintaka"; import { JavaScriptRuntime } from "./node"; import { JsonCasing, JwtDecoder } from "@tribufu/mintaka"; import { TokenPayload } from "./token"; import { TRIBUFU_API_URL, TRIBUFU_VERSION } from "."; import { TribufuApiOptions } from "./options"; /** * **Tribufu API** * * Use this class to interact with the Tribufu API. * * *There are three ways to use the Tribufu API:* * - A api key give you public read only access to the Tribufu API. * - A bot give you read and write access to the Tribufu API as a bot account. * - A client give you read and write access to the Tribufu API as a client application. */ export class TribufuApi { protected readonly http: HttpClient; protected readonly options: TribufuApiOptions; constructor(options?: TribufuApiOptions | null) { this.options = options || {}; this.http = new HttpClient({ baseUrl: TribufuApi.getBaseUrl(), headers: TribufuApi.defaultHeaders(), logEnabled: TribufuApi.debugEnabled(), jsonRequestCasing: JsonCasing.SnakeCase, jsonResponseCasing: JsonCasing.CamelCase, }); } /** * Create a TribufuApi with the default options. * @returns */ public static default(): TribufuApi { return new TribufuApi(); } /** * Create a TribufuApi with the given api key. * * - A api key give you public read only access to the Tribufu API. * * @param apiKey * @returns TribufuApi */ public static withApiKey(apiKey: string): TribufuApi { return new TribufuApi({ apiKey }); } /** * Try to create a TribufuApi from environment variables. * * - This will only work if the environment variables are set. * * @param prefix A prefix for the environment variables. * @returns TribufuApi | null * @example * ```ts * // process.env.TRIBUFU_API_KEY * const api = TribufuApi.fromEnv("TRIBUFU"); * ``` */ public static fromEnv(prefix?: string | null): TribufuApi | null { const envPrefix = prefix ? `${prefix}_` : ""; const apiKey = process.env[`${envPrefix}API_KEY`]; if (apiKey) { return TribufuApi.withApiKey(apiKey); } return null; } /** * Create a TribufuApi from environment variables or the default api. * * - This will fallback to the default api if the environment variables are not set. * * @param prefix A prefix for the environment variables. * @returns TribufuApi | null * @example * ```ts * // process.env.TRIBUFU_API_KEY = null * const api = TribufuApi.fromEnvOrDefault("TRIBUFU_"); * ``` */ public static fromEnvOrDefault(prefix: string = ""): TribufuApi { return TribufuApi.fromEnv(prefix) || TribufuApi.default(); } /** * Check if debug mode is enabled. * * - Debug mode is enabled if the environment variable `NODE_ENV` is set to `development`. * - Debug mode is disabled by default. * - Debug mode is disabled in the browser. * * @returns boolean */ private static debugEnabled(): boolean { return process.env.NODE_ENV ? process.env.NODE_ENV === "development" : false; } /** * Get the base url for the Tribufu API. * * - The base url can be set using the environment variable `TRIBUFU_API_URL`. * - The custom base url is only used if debug mode is enabled. * - The default base url is `https://api.tribufu.com`. * * @returns string */ private static getBaseUrl(): string { const baseUrl = process.env[`TRIBUFU_API_URL`] || null; return TribufuApi.debugEnabled() && baseUrl ? baseUrl : TRIBUFU_API_URL; } /** * Get the default headers for the Tribufu API. * @returns HeaderMap */ private static defaultHeaders(): HttpHeaders { const headers = new HttpHeaders(); headers.set("X-Tribufu-Language", "javascript"); headers.set("X-Tribufu-Version", TRIBUFU_VERSION); return headers; } /** * Detect the current JavaScript runtime. * * - This is used to determine if the code is running in a browser or in Node.js. * * @returns JavaScriptRuntime */ private static detectRuntime(): JavaScriptRuntime { if (typeof window !== "undefined") { return JavaScriptRuntime.Browser; } if (typeof process !== "undefined" && process?.versions?.node) { return JavaScriptRuntime.Node; } return JavaScriptRuntime.Other; } /** * Check if the current JavaScript runtime is a browser. * @returns boolean */ public static isBrowser(): boolean { return TribufuApi.detectRuntime() === JavaScriptRuntime.Browser; } /** * Check if the current JavaScript runtime is Node.js. * @returns boolean */ public static isNode(): boolean { return TribufuApi.detectRuntime() === JavaScriptRuntime.Node; } /** * Extract the payload from a Tribufu token. * @param token * @returns TokenPayload | null */ protected static parseToken(token: string): TokenPayload | null { try { const payload = JwtDecoder.decode(token); if (!payload) { return null; } return payload as TokenPayload; } catch (error) { return null; } } /** * Get current headers with the api key or access token. * @returns HeaderMap */ protected getHeaders(): HttpHeaders { let headers = TribufuApi.defaultHeaders(); if (this.options.apiKey) { headers.set("Authorization", `ApiKey ${this.options.apiKey}`); return headers; } if (this.options.accessToken) { headers.set("Authorization", `Bearer ${this.options.accessToken}`); return headers; } return headers; } /** * Get games from the Tribufu API. * @param page * @returns Game[] */ public async getGames(page: number = 1): Promise { const headers = this.getHeaders(); const responseBody = await this.http.get(`/v1/packages?page=${page}`, headers); if (!responseBody) { return []; } return responseBody; } /** * Get a game from the Tribufu API. * @param id * @returns Game | null */ public async getGameById(id: string): Promise { const headers = this.getHeaders(); const responseBody = await this.http.get(`/v1/packages/${id}`, headers); if (!responseBody) { return null; } return responseBody; } /** * Get a game from the Tribufu API. * @param page * @returns Server[] */ public async getServers(page: number = 1): Promise { const headers = this.getHeaders(); const responseBody = await this.http.get(`/v1/servers?page=${page}`, headers); if (!responseBody) { return []; } return responseBody; } /** * Get a server by id or address from the Tribufu API. * @param idOrAddress * @returns Server | null */ public async getServer(idOrAddress: string): Promise { if (isNaN(idOrAddress as any)) { return await this.getServerByAddress(idOrAddress); } return await this.getServerById(idOrAddress); } /** * Get a server by id from the Tribufu API. * @param id * @returns Server | null */ public async getServerById(id: string): Promise { const headers = this.getHeaders() const responseBody = await this.http.get(`/v1/servers/${id}`, headers); if (!responseBody) { return null; } return responseBody; } /** * Get a server by address from the Tribufu API. * @param address * @returns Server | null */ public async getServerByAddress(address: string): Promise { const headers = this.getHeaders(); const responseBody = await this.http.get(`/v1/servers/address/${address}`, headers); if (!responseBody) { return null; } return responseBody; } /** * Get a user by id from the Tribufu API. * @param id * @returns User | null */ public async getUserById(id: string): Promise { const headers = this.getHeaders(); const responseBody = await this.http.get(`/v1/users/${id}`, headers); if (!responseBody) { return null; } return responseBody; } /** * Get a user by uuid from the Tribufu API. * @param uuid * @returns User[] */ public async getUserByUuid(uuid: string): Promise { return await this.getUserByKey("uuid", uuid); } /** * Get a user by name from the Tribufu API. * @param uuid * @returns User[] */ public async getUserByName(name: string): Promise { return await this.getUserByKey("name", name); } /** * Get a user by email from the Tribufu API. * @param uuid * @returns User[] */ public async getUserByEmail(email: string): Promise { return await this.getUserByKey("email", email); } /** * Get a user by custom key from the Tribufu API. * @param key * @param value * @returns User[] */ private async getUserByKey(key: string, value: string): Promise { const headers = this.getHeaders(); const responseBody = await this.http.get(`/v1/users/?${key}=${value}`, headers); if (!responseBody) { return []; } return responseBody; } /** * Get all servers for a user from the Tribufu API. * @param userId * @returns Server[] */ public async getUserServers(userId: string): Promise { const headers = this.getHeaders(); const responseBody = await this.http.get(`/v1/users/${userId}/servers`, headers); if (!responseBody) { return []; } return responseBody; } /** * Get a oauth2 client by id from the Tribufu API. * @param id * @returns Client | null */ protected async getClientById(id: string): Promise { const headers = this.getHeaders(); const responseBody = await this.http.get(`/v1/oauth2/clients/${id}`, headers); if (!responseBody) { return null; } return responseBody; } }