From 3bc20c99b95d3392a620dfd4dc5427c3b902f82e Mon Sep 17 00:00:00 2001 From: Guilherme Werner Date: Tue, 2 Jan 2024 08:17:25 -0300 Subject: [PATCH] Create http wrapper --- src/api.ts | 126 ++----------------- src/client.ts | 16 ++- src/http.ts | 17 --- src/http/index.ts | 192 +++++++++++++++++++++++++++++ src/{oauth2.ts => oauth2/index.ts} | 0 src/socket/index.ts | 11 ++ 6 files changed, 220 insertions(+), 142 deletions(-) delete mode 100644 src/http.ts create mode 100644 src/http/index.ts rename src/{oauth2.ts => oauth2/index.ts} (100%) create mode 100644 src/socket/index.ts diff --git a/src/api.ts b/src/api.ts index b19f3a5..9ded640 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,6 +1,6 @@ // Copyright (c) Tribufu. All Rights Reserved. -import { HeaderMap } from "./http"; +import { HeaderMap, TribufuHttp } from "./http"; import { JavaScriptRuntime } from "./node"; import { TribufuApiOptions } from "./options"; import { TribufuBot } from "./bot"; @@ -24,39 +24,17 @@ import snakecaseKeys from "snakecase-keys"; * - A client give you read and write access to the Tribufu API as a client application. */ export class TribufuApi { + protected readonly http: TribufuHttp; protected readonly options: TribufuApiOptions; - protected readonly http: AxiosInstance; constructor(options?: TribufuApiOptions | null) { this.options = options || {}; - let http = axios.create({ - baseURL: TribufuApi.getBaseUrl(), + this.http = new TribufuHttp({ + baseUrl: TribufuApi.getBaseUrl(), headers: TribufuApi.defaultHeaders(), + logEnabled: TribufuApi.debugEnabled(), }); - - http.interceptors.request.use((req) => { - if (TribufuApi.debugEnabled()) { - console.log(`(TribufuApi) ${req.method?.toUpperCase()} ${req.baseURL}${req.url}`); - } - - const contentType = req.headers["Content-Type"]; - if (req.data && (contentType === "application/json" || contentType === "application/x-www-form-urlencoded")) { - req.data = snakecaseKeys(req.data); - } - - return req; - }); - - http.interceptors.response.use((res) => { - if (res.data) { - res.data = camelcaseKeys(res.data); - } - - return res; - }); - - this.http = http; } /** @@ -235,90 +213,6 @@ export class TribufuApi { return headers; } - /** - * Get a resource from the Tribufu API. - * @returns T | null - */ - protected async get(path: string, headers?: HeaderMap | null): Promise { - try { - const requestHeaders = headers || this.getHeaders(); - const response = await this.http.get(path, { headers: requestHeaders }); - - if (response.status !== 200) { - return null; - } - - return response.data as T; - } catch (error) { - return null; - } - } - - /** - * Create a resource to the Tribufu API. - * @param path - * @param body - * @param headers - * @returns T | null - */ - protected async post(path: string, body: S, headers?: HeaderMap | null): Promise { - try { - const requestHeaders = headers || this.getHeaders(); - const response = await this.http.post(path, body, { headers: requestHeaders }); - - if (response.status !== 200) { - return null; - } - - return response.data as T; - } catch (error) { - return null; - } - } - - /** - * Update a resource on the Tribufu API. - * @param path - * @param body - * @param headers - * @returns T | null - */ - protected async put(path: string, body: S, headers?: HeaderMap | null): Promise { - try { - const requestHeaders = headers || this.getHeaders(); - const response = await this.http.put(path, body, { headers: requestHeaders }); - - if (response.status !== 200) { - return null; - } - - return response.data as T; - } catch (error) { - return null; - } - } - - /** - * Delete a resource from the Tribufu API. - * @param path - * @param headers - * @returns T | null - */ - protected async delete(path: string, headers?: HeaderMap | null): Promise { - try { - const requestHeaders = headers || this.getHeaders(); - const response = await this.http.delete(path, { headers: requestHeaders }); - - if (response.status !== 200) { - return null; - } - - return response.data as T; - } catch (error) { - return null; - } - } - /** * Get games from the Tribufu API. * @param page @@ -326,7 +220,7 @@ export class TribufuApi { */ public async getGames(page: number = 1): Promise { const headers = this.getHeaders(); - const responseBody = await this.get(`/v1/packages?page=${page}`, headers); + const responseBody = await this.http.get(`/v1/packages?page=${page}`, headers); if (!responseBody) { return []; @@ -342,7 +236,7 @@ export class TribufuApi { */ public async getGameyId(id: string): Promise { const headers = this.getHeaders(); - const responseBody = await this.get(`/v1/packages/${id}`, headers); + const responseBody = await this.http.get(`/v1/packages/${id}`, headers); if (!responseBody) { return null; @@ -358,7 +252,7 @@ export class TribufuApi { */ public async getServers(page: number = 1): Promise { const headers = this.getHeaders(); - const responseBody = await this.get(`/v1/servers?page=${page}`, headers); + const responseBody = await this.http.get(`/v1/servers?page=${page}`, headers); if (!responseBody) { return []; @@ -387,7 +281,7 @@ export class TribufuApi { */ public async getServerById(id: string): Promise { const headers = this.getHeaders() - const responseBody = await this.get(`/v1/servers/${id}`, headers); + const responseBody = await this.http.get(`/v1/servers/${id}`, headers); if (!responseBody) { return null; @@ -403,7 +297,7 @@ export class TribufuApi { */ public async getServerByAddress(address: string): Promise { const headers = this.getHeaders(); - const responseBody = await this.get(`/v1/servers/address/${address}`, headers); + const responseBody = await this.http.get(`/v1/servers/address/${address}`, headers); if (!responseBody) { return null; diff --git a/src/client.ts b/src/client.ts index 4ba80a5..9634cf3 100644 --- a/src/client.ts +++ b/src/client.ts @@ -251,7 +251,7 @@ export class TribufuClient extends TribufuApi { const url = `/v1/oauth2/introspect`; const headers = this.getOAuthHeaders(); - const responseBody = await this.post(url, requestBody, headers); + const responseBody = await this.http.post(url, requestBody, headers); if (!responseBody) { return null; @@ -276,7 +276,7 @@ export class TribufuClient extends TribufuApi { const url = `/v1/oauth2/revoke`; const headers = this.getOAuthHeaders(); - const responseBody = await this.post(url, requestBody, headers); + const responseBody = await this.http.post(url, requestBody, headers); if (!responseBody) { return false; @@ -324,7 +324,7 @@ export class TribufuClient extends TribufuApi { const params = subjectKey && subjectValue ? `?${subjectKey}=${subjectValue}` : ""; const url = `/v1/oauth2/token${params}`; const headers = this.getOAuthHeaders(); - const responseBody = await this.post(url, requestBody, headers); + const responseBody = await this.http.post(url, requestBody, headers); if (!responseBody) { return null; @@ -338,19 +338,17 @@ export class TribufuClient extends TribufuApi { * @returns User | null */ public async getUserInfo(): Promise { - if (!this.options.refreshToken) { + if (!this.options.accessToken) { return null; } const headers = this.getHeaders(); - const response = await this.http.get(`/v1/oauth2/userinfo`, { headers }); + const responseBody = await this.http.get(`/v1/oauth2/userinfo`, headers); - if (response.status !== 200) { + if (!responseBody) { return null; } - const user = response.data as User; - - return user; + return responseBody; } } diff --git a/src/http.ts b/src/http.ts deleted file mode 100644 index 577aedb..0000000 --- a/src/http.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Tribufu. All Rights Reserved. - -export type HeaderMap = { - [key: string]: string -}; - -export type CookieMap = { - [key: string]: string; -}; - -export interface ErrorResponse { - error: string; -}; - -export interface MessageResponse { - message: string; -}; diff --git a/src/http/index.ts b/src/http/index.ts new file mode 100644 index 0000000..1f9e96e --- /dev/null +++ b/src/http/index.ts @@ -0,0 +1,192 @@ +// Copyright (c) Tribufu. All Rights Reserved. + +import axios, { AxiosInstance } from "axios"; +import camelcaseKeys from "camelcase-keys"; +import snakecaseKeys from "snakecase-keys"; + +export type HeaderMap = { + [key: string]: string +}; + +export type CookieMap = { + [key: string]: string; +}; + +export interface ErrorResponse { + error: string; +}; + +export interface MessageResponse { + message: string; +}; + +export interface TribufuHttpOptions { + baseUrl?: string | null; + headers?: HeaderMap; + logEnabled?: boolean; + logTarget?: string; +}; + +/** + * Tribufu Http + * + * Helper class to make HTTP requests to the Tribufu API. + */ +export class TribufuHttp { + private readonly inner: AxiosInstance; + protected readonly options: TribufuHttpOptions; + + constructor(options?: TribufuHttpOptions | null) { + const defaultOptions = TribufuHttp.defaultOptions(); + + this.options = { + baseUrl: options?.baseUrl || defaultOptions.baseUrl, + headers: options?.headers || defaultOptions.headers, + logEnabled: options?.logEnabled || defaultOptions.logEnabled, + logTarget: options?.logTarget || defaultOptions.logTarget, + }; + + const inner = axios.create({ + baseURL: this.options?.baseUrl || undefined, + headers: this.options?.headers || undefined, + }); + + inner.interceptors.request.use((req) => { + if (this.options.logEnabled ?? false) { + console.log(`(${this.options.logTarget}) ${req.method?.toUpperCase()} ${req.baseURL}${req.url}`); + } + + const contentType = req.headers["Content-Type"]; + if (req.data && (contentType === "application/json" || contentType === "application/x-www-form-urlencoded")) { + req.data = snakecaseKeys(req.data); + } + + return req; + }); + + inner.interceptors.response.use((res) => { + if (res.data) { + res.data = camelcaseKeys(res.data); + } + + return res; + }); + + this.inner = inner; + } + + private static defaultOptions(): TribufuHttpOptions { + return { + baseUrl: null, + headers: {}, + logEnabled: false, + logTarget: "TribufuHttp", + }; + }; + + /** + * Get a resource from the Tribufu API. + * @returns T | null + */ + public async get(path: string, headers?: HeaderMap | null): Promise { + try { + const requestHeaders = headers || this.options.headers; + const response = await this.inner.get(path, { headers: requestHeaders }); + + if (response.status !== 200) { + return null; + } + + return response.data as T; + } catch (error) { + return null; + } + } + + /** + * Create a resource to the Tribufu API. + * @param path + * @param body + * @param headers + * @returns T | null + */ + public async post(path: string, body: S, headers?: HeaderMap | null): Promise { + try { + const requestHeaders = headers || this.options.headers; + const response = await this.inner.post(path, body, { headers: requestHeaders }); + + if (response.status !== 200) { + return null; + } + + return response.data as T; + } catch (error) { + return null; + } + } + + /** + * Update a resource on the Tribufu API. + * @param path + * @param body + * @param headers + * @returns T | null + */ + public async put(path: string, body: S, headers?: HeaderMap | null): Promise { + try { + const requestHeaders = headers || this.options.headers; + const response = await this.inner.put(path, body, { headers: requestHeaders }); + + if (response.status !== 200) { + return null; + } + + return response.data as T; + } catch (error) { + return null; + } + } + + /** + * Patch a resource on the Tribufu API. + * @param path + * @param body + * @param headers + * @returns T | null + */ + public async patch(path: string, body: S, headers?: HeaderMap | null): Promise { + try { + const requestHeaders = headers || this.options.headers; + const response = await this.inner.patch(path, body, { headers: requestHeaders }); + + if (response.status !== 200) { + return null; + } + + return response.data as T; + } catch (error) { + return null; + } + } + + /** + * Delete a resource from the Tribufu API. + * @param path + * @param headers + * @returns T | null + */ + public async delete(path: string, headers?: HeaderMap | null): Promise { + try { + const requestHeaders = headers || this.options.headers; + const response = await this.inner.delete(path, { headers: requestHeaders }); + + if (response.status !== 200) { + return null; + } + + return response.data as T; + } catch (error) { + return null; + } + } +} diff --git a/src/oauth2.ts b/src/oauth2/index.ts similarity index 100% rename from src/oauth2.ts rename to src/oauth2/index.ts diff --git a/src/socket/index.ts b/src/socket/index.ts new file mode 100644 index 0000000..ab6cc5f --- /dev/null +++ b/src/socket/index.ts @@ -0,0 +1,11 @@ +// Copyright (c) Tribufu. All Rights Reserved. + +/** + * Tribufu Socket + * + * Helper class to connect to the Tribufu Socket API. + */ +export class TribufuSocket { + constructor() { + } +}