refactor: add response data generic type (#4567)

* remove unnecessary type

* remove unnecessary type

* data should always be returned

* added datatype generic

* renamed EndpointData to Endpoint

* replaced two defaults with one

* rename type

* removed logs

* renamed generic
This commit is contained in:
Jack 2023-08-21 16:48:17 +02:00 committed by GitHub
parent 0086398073
commit 38c9d0c82a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 89 additions and 84 deletions

View file

@ -40,7 +40,7 @@ function apeifyClientMethod(
return async (
endpoint: string,
options: Ape.RequestOptions = {}
): Ape.EndpointData => {
): Ape.EndpointResponse => {
let errorMessage = "";
try {
@ -62,7 +62,7 @@ function apeifyClientMethod(
);
}
const { message, data } = response.data as Ape.ApiResponse;
const { message, data } = response.data;
return {
status: response.status,
@ -87,6 +87,7 @@ function apeifyClientMethod(
return {
status: 500,
message: errorMessage,
data: null,
};
};
}

View file

@ -5,11 +5,11 @@ export default class ApeKeys {
this.httpClient = httpClient;
}
async get(): Ape.EndpointData {
async get(): Ape.EndpointResponse {
return await this.httpClient.get(BASE_PATH);
}
async generate(name: string, enabled: boolean): Ape.EndpointData {
async generate(name: string, enabled: boolean): Ape.EndpointResponse {
const payload = { name, enabled };
return await this.httpClient.post(BASE_PATH, { payload });
}
@ -17,12 +17,12 @@ export default class ApeKeys {
async update(
apeKeyId: string,
updates: { name?: string; enabled?: boolean }
): Ape.EndpointData {
): Ape.EndpointResponse {
const payload = { ...updates };
return await this.httpClient.patch(`${BASE_PATH}/${apeKeyId}`, { payload });
}
async delete(apeKeyId: string): Ape.EndpointData {
async delete(apeKeyId: string): Ape.EndpointResponse {
return await this.httpClient.delete(`${BASE_PATH}/${apeKeyId}`);
}
}

View file

@ -5,11 +5,11 @@ export default class Configs {
this.httpClient = httpClient;
}
async get(): Ape.EndpointData {
async get(): Ape.EndpointResponse {
return await this.httpClient.get(BASE_PATH);
}
async save(config: MonkeyTypes.Config): Ape.EndpointData {
async save(config: MonkeyTypes.Config): Ape.EndpointResponse {
return await this.httpClient.patch(BASE_PATH, { payload: { config } });
}
}

View file

@ -18,7 +18,7 @@ export default class Leaderboards {
this.httpClient = httpClient;
}
async get(query: LeadeboardQueryWithPagination): Ape.EndpointData {
async get(query: LeadeboardQueryWithPagination): Ape.EndpointResponse {
const {
language,
mode,
@ -44,7 +44,7 @@ export default class Leaderboards {
return await this.httpClient.get(endpointPath, { searchQuery });
}
async getRank(query: LeaderboardQuery): Ape.EndpointData {
async getRank(query: LeaderboardQuery): Ape.EndpointResponse {
const { language, mode, mode2, isDaily, daysBefore } = query;
const includeDaysBefore = isDaily && daysBefore;

View file

@ -5,14 +5,14 @@ export default class Presets {
this.httpClient = httpClient;
}
async get(): Ape.EndpointData {
async get(): Ape.EndpointResponse {
return await this.httpClient.get(BASE_PATH);
}
async add(
presetName: string,
configChanges: MonkeyTypes.ConfigChanges
): Ape.EndpointData {
): Ape.EndpointResponse {
const payload = {
name: presetName,
config: configChanges,
@ -25,7 +25,7 @@ export default class Presets {
presetId: string,
presetName: string,
configChanges: MonkeyTypes.ConfigChanges
): Ape.EndpointData {
): Ape.EndpointResponse {
const payload = {
_id: presetId,
name: presetName,
@ -35,7 +35,7 @@ export default class Presets {
return await this.httpClient.patch(BASE_PATH, { payload });
}
async delete(presetId: string): Ape.EndpointData {
async delete(presetId: string): Ape.EndpointResponse {
return await this.httpClient.delete(`${BASE_PATH}/${presetId}`);
}
}

View file

@ -5,7 +5,7 @@ export default class Psas {
this.httpClient = httpClient;
}
async get(): Ape.EndpointData {
async get(): Ape.EndpointResponse {
return await this.httpClient.get(BASE_PATH);
}
}

View file

@ -11,13 +11,13 @@ export default class Public {
this.httpClient = httpClient;
}
async getSpeedHistogram(searchQuery: SpeedStatsQuery): Ape.EndpointData {
async getSpeedHistogram(searchQuery: SpeedStatsQuery): Ape.EndpointResponse {
return await this.httpClient.get(`${BASE_PATH}/speedHistogram`, {
searchQuery,
});
}
async getTypingStats(): Ape.EndpointData {
async getTypingStats(): Ape.EndpointResponse {
return await this.httpClient.get(`${BASE_PATH}/typingStats`);
}
}

View file

@ -5,11 +5,11 @@ export default class Quotes {
this.httpClient = httpClient;
}
async get(): Ape.EndpointData {
async get(): Ape.EndpointResponse {
return await this.httpClient.get(BASE_PATH);
}
async isSubmissionEnabled(): Ape.EndpointData {
async isSubmissionEnabled(): Ape.EndpointResponse {
return await this.httpClient.get(`${BASE_PATH}/isSubmissionEnabled`);
}
@ -18,7 +18,7 @@ export default class Quotes {
source: string,
language: string,
captcha: string
): Ape.EndpointData {
): Ape.EndpointResponse {
const payload = {
text,
source,
@ -33,7 +33,7 @@ export default class Quotes {
quoteSubmissionId: string,
editText?: string,
editSource?: string
): Ape.EndpointData {
): Ape.EndpointResponse {
const payload = {
quoteId: quoteSubmissionId,
editText,
@ -43,13 +43,13 @@ export default class Quotes {
return await this.httpClient.post(`${BASE_PATH}/approve`, { payload });
}
async rejectSubmission(quoteSubmissionId: string): Ape.EndpointData {
async rejectSubmission(quoteSubmissionId: string): Ape.EndpointResponse {
return await this.httpClient.post(`${BASE_PATH}/reject`, {
payload: { quoteId: quoteSubmissionId },
});
}
async getRating(quote: MonkeyTypes.Quote): Ape.EndpointData {
async getRating(quote: MonkeyTypes.Quote): Ape.EndpointResponse {
const searchQuery = {
quoteId: quote.id,
language: quote.language,
@ -58,7 +58,10 @@ export default class Quotes {
return await this.httpClient.get(`${BASE_PATH}/rating`, { searchQuery });
}
async addRating(quote: MonkeyTypes.Quote, rating: number): Ape.EndpointData {
async addRating(
quote: MonkeyTypes.Quote,
rating: number
): Ape.EndpointResponse {
const payload = {
quoteId: quote.id,
rating,
@ -74,7 +77,7 @@ export default class Quotes {
reason: string,
comment: string,
captcha: string
): Ape.EndpointData {
): Ape.EndpointResponse {
const payload = {
quoteId,
quoteLanguage,

View file

@ -5,23 +5,25 @@ export default class Results {
this.httpClient = httpClient;
}
async get(): Ape.EndpointData {
async get(): Ape.EndpointResponse {
return await this.httpClient.get(BASE_PATH);
}
async save(result: MonkeyTypes.Result<MonkeyTypes.Mode>): Ape.EndpointData {
async save(
result: MonkeyTypes.Result<MonkeyTypes.Mode>
): Ape.EndpointResponse {
return await this.httpClient.post(BASE_PATH, {
payload: { result },
});
}
async updateTags(resultId: string, tagIds: string[]): Ape.EndpointData {
async updateTags(resultId: string, tagIds: string[]): Ape.EndpointResponse {
return await this.httpClient.patch(`${BASE_PATH}/tags`, {
payload: { resultId, tagIds },
});
}
async deleteAll(): Ape.EndpointData {
async deleteAll(): Ape.EndpointResponse {
return await this.httpClient.delete(BASE_PATH);
}
}

View file

@ -5,7 +5,7 @@ export default class Users {
this.httpClient = httpClient;
}
async getData(): Ape.EndpointData {
async getData(): Ape.EndpointResponse {
return await this.httpClient.get(BASE_PATH);
}
@ -14,7 +14,7 @@ export default class Users {
captcha: string,
email?: string,
uid?: string
): Ape.EndpointData {
): Ape.EndpointResponse {
const payload = {
email,
name,
@ -25,23 +25,23 @@ export default class Users {
return await this.httpClient.post(`${BASE_PATH}/signup`, { payload });
}
async getNameAvailability(name: string): Ape.EndpointData {
async getNameAvailability(name: string): Ape.EndpointResponse {
return await this.httpClient.get(`${BASE_PATH}/checkName/${name}`);
}
async delete(): Ape.EndpointData {
async delete(): Ape.EndpointResponse {
return await this.httpClient.delete(BASE_PATH);
}
async reset(): Ape.EndpointData {
async reset(): Ape.EndpointResponse {
return await this.httpClient.patch(`${BASE_PATH}/reset`);
}
async optOutOfLeaderboards(): Ape.EndpointData {
async optOutOfLeaderboards(): Ape.EndpointResponse {
return await this.httpClient.post(`${BASE_PATH}/optOutOfLeaderboards`);
}
async updateName(name: string): Ape.EndpointData {
async updateName(name: string): Ape.EndpointResponse {
return await this.httpClient.patch(`${BASE_PATH}/name`, {
payload: { name },
});
@ -52,7 +52,7 @@ export default class Users {
mode2: MonkeyTypes.Mode2<M>,
language: string,
rank: number
): Ape.EndpointData {
): Ape.EndpointResponse {
const payload = {
mode,
mode2,
@ -65,7 +65,10 @@ export default class Users {
});
}
async updateEmail(newEmail: string, previousEmail: string): Ape.EndpointData {
async updateEmail(
newEmail: string,
previousEmail: string
): Ape.EndpointResponse {
const payload = {
newEmail,
previousEmail,
@ -74,35 +77,35 @@ export default class Users {
return await this.httpClient.patch(`${BASE_PATH}/email`, { payload });
}
async deletePersonalBests(): Ape.EndpointData {
async deletePersonalBests(): Ape.EndpointResponse {
return await this.httpClient.delete(`${BASE_PATH}/personalBests`);
}
async addResultFilterPreset(
filter: MonkeyTypes.ResultFilters
): Ape.EndpointData {
): Ape.EndpointResponse {
return await this.httpClient.post(`${BASE_PATH}/resultFilterPresets`, {
payload: filter,
});
}
async removeResultFilterPreset(id: string): Ape.EndpointData {
async removeResultFilterPreset(id: string): Ape.EndpointResponse {
return await this.httpClient.delete(
`${BASE_PATH}/resultFilterPresets/${id}`
);
}
async getTags(): Ape.EndpointData {
async getTags(): Ape.EndpointResponse {
return await this.httpClient.get(`${BASE_PATH}/tags`);
}
async createTag(tagName: string): Ape.EndpointData {
async createTag(tagName: string): Ape.EndpointResponse {
return await this.httpClient.post(`${BASE_PATH}/tags`, {
payload: { tagName },
});
}
async editTag(tagId: string, newName: string): Ape.EndpointData {
async editTag(tagId: string, newName: string): Ape.EndpointResponse {
const payload = {
tagId,
newName,
@ -111,24 +114,24 @@ export default class Users {
return await this.httpClient.patch(`${BASE_PATH}/tags`, { payload });
}
async deleteTag(tagId: string): Ape.EndpointData {
async deleteTag(tagId: string): Ape.EndpointResponse {
return await this.httpClient.delete(`${BASE_PATH}/tags/${tagId}`);
}
async deleteTagPersonalBest(tagId: string): Ape.EndpointData {
async deleteTagPersonalBest(tagId: string): Ape.EndpointResponse {
return await this.httpClient.delete(
`${BASE_PATH}/tags/${tagId}/personalBest`
);
}
async getCustomThemes(): Ape.EndpointData {
async getCustomThemes(): Ape.EndpointResponse {
return await this.httpClient.get(`${BASE_PATH}/customThemes`);
}
async editCustomTheme(
themeId: string,
newTheme: Partial<MonkeyTypes.CustomTheme>
): Ape.EndpointData {
): Ape.EndpointResponse {
const payload = {
themeId: themeId,
theme: {
@ -141,7 +144,7 @@ export default class Users {
});
}
async deleteCustomTheme(themeId: string): Ape.EndpointData {
async deleteCustomTheme(themeId: string): Ape.EndpointResponse {
const payload = {
themeId: themeId,
};
@ -152,12 +155,12 @@ export default class Users {
async addCustomTheme(
newTheme: Partial<MonkeyTypes.CustomTheme>
): Ape.EndpointData {
): Ape.EndpointResponse {
const payload = { name: newTheme.name, colors: newTheme.colors };
return await this.httpClient.post(`${BASE_PATH}/customThemes`, { payload });
}
async getOauthLink(): Ape.EndpointData {
async getOauthLink(): Ape.EndpointResponse {
return await this.httpClient.get(`${BASE_PATH}/discord/oauth`);
}
@ -165,20 +168,20 @@ export default class Users {
tokenType: string,
accessToken: string,
state: string
): Ape.EndpointData {
): Ape.EndpointResponse {
return await this.httpClient.post(`${BASE_PATH}/discord/link`, {
payload: { tokenType, accessToken, state },
});
}
async unlinkDiscord(): Ape.EndpointData {
async unlinkDiscord(): Ape.EndpointResponse {
return await this.httpClient.post(`${BASE_PATH}/discord/unlink`);
}
async addQuoteToFavorites(
language: string,
quoteId: string
): Ape.EndpointData {
): Ape.EndpointResponse {
const payload = { language, quoteId };
return await this.httpClient.post(`${BASE_PATH}/favoriteQuotes`, {
payload,
@ -188,25 +191,25 @@ export default class Users {
async removeQuoteFromFavorites(
language: string,
quoteId: string
): Ape.EndpointData {
): Ape.EndpointResponse {
const payload = { language, quoteId };
return await this.httpClient.delete(`${BASE_PATH}/favoriteQuotes`, {
payload,
});
}
async getProfileByUid(uid: string): Promise<Ape.EndpointData> {
async getProfileByUid(uid: string): Promise<Ape.EndpointResponse> {
return await this.httpClient.get(`${BASE_PATH}/${uid}/profile?isUid`);
}
async getProfileByName(name: string): Promise<Ape.EndpointData> {
async getProfileByName(name: string): Promise<Ape.EndpointResponse> {
return await this.httpClient.get(`${BASE_PATH}/${name}/profile`);
}
async updateProfile(
profileUpdates: Partial<MonkeyTypes.UserDetails>,
selectedBadgeId?: number
): Promise<Ape.EndpointData> {
): Promise<Ape.EndpointResponse> {
return await this.httpClient.patch(`${BASE_PATH}/profile`, {
payload: {
...profileUpdates,
@ -215,14 +218,14 @@ export default class Users {
});
}
async getInbox(): Promise<Ape.EndpointData> {
async getInbox(): Promise<Ape.EndpointResponse> {
return await this.httpClient.get(`${BASE_PATH}/inbox`);
}
async updateInbox(options: {
mailIdsToDelete?: string[];
mailIdsToMarkRead?: string[];
}): Promise<Ape.EndpointData> {
}): Promise<Ape.EndpointResponse> {
const payload = {
mailIdsToDelete: options.mailIdsToDelete,
mailIdsToMarkRead: options.mailIdsToMarkRead,
@ -235,7 +238,7 @@ export default class Users {
reason: string,
comment: string,
captcha: string
): Ape.EndpointData {
): Ape.EndpointResponse {
const payload = {
uid,
reason,
@ -246,17 +249,17 @@ export default class Users {
return await this.httpClient.post(`${BASE_PATH}/report`, { payload });
}
async verificationEmail(): Ape.EndpointData {
async verificationEmail(): Ape.EndpointResponse {
return await this.httpClient.get(`${BASE_PATH}/verificationEmail`);
}
async forgotPasswordEmail(email: string): Ape.EndpointData {
async forgotPasswordEmail(email: string): Ape.EndpointResponse {
return await this.httpClient.post(`${BASE_PATH}/forgotPasswordEmail`, {
payload: { email },
});
}
async setStreakHourOffset(hourOffset: number): Ape.EndpointData {
async setStreakHourOffset(hourOffset: number): Ape.EndpointResponse {
return await this.httpClient.post(`${BASE_PATH}/setStreakHourOffset`, {
payload: { hourOffset },
});

View file

@ -5,13 +5,13 @@ declare namespace Ape {
payload?: any;
}
interface HttpClientResponse {
interface HttpClientResponse<Data> {
status: number;
message: string;
data?: any;
data: Data | null;
}
type EndpointData = Promise<HttpClientResponse>;
type EndpointResponse<Data = any> = Promise<HttpClientResponse<Data>>;
type HttpClientMethod = (
endpoint: string,
@ -27,9 +27,4 @@ declare namespace Ape {
}
type HttpMethodTypes = keyof HttpClient;
interface ApiResponse {
message: string;
data: any | null;
}
}

View file

@ -1,10 +1,10 @@
type ShouldRetryCallback = (
type ShouldRetryCallback<ResponseDataType> = (
statusCode: number,
response?: Ape.HttpClientResponse
response?: Ape.HttpClientResponse<ResponseDataType>
) => boolean;
interface RetryOptions {
shouldRetry?: ShouldRetryCallback;
interface RetryOptions<ResponseDataType = any> {
shouldRetry?: ShouldRetryCallback<ResponseDataType>;
retryAttempts?: number;
retryDelayMs?: number;
}
@ -19,14 +19,14 @@ const DEFAULT_RETRY_OPTIONS: Required<RetryOptions> = {
retryDelayMs: 3000,
};
export async function withRetry(
fn: () => Ape.EndpointData,
opts?: RetryOptions
): Ape.EndpointData {
export async function withRetry<ResponseDataType>(
fn: () => Ape.EndpointResponse<ResponseDataType>,
opts?: RetryOptions<ResponseDataType>
): Ape.EndpointResponse {
const retry = async (
previousData: Ape.HttpClientResponse,
completeOpts: Required<RetryOptions>
): Promise<Ape.HttpClientResponse> => {
previousData: Ape.HttpClientResponse<ResponseDataType>,
completeOpts: Required<RetryOptions<ResponseDataType>>
): Promise<Ape.HttpClientResponse<ResponseDataType>> => {
const { retryAttempts, shouldRetry, retryDelayMs } = completeOpts;
if (retryAttempts <= 0 || !shouldRetry(previousData.status, previousData)) {

View file

@ -91,7 +91,7 @@ export async function initSnapshot(): Promise<
configResponse,
tagsResponse,
presetsResponse,
].map((response: Ape.HttpClientResponse) => response.data);
].map((response) => response.data);
snap.name = userData.name;
snap.personalBests = userData.personalBests;

View file

@ -20,6 +20,7 @@ function setMemory(id: string): void {
async function getLatest(): Promise<MonkeyTypes.PSA[] | null> {
const response = await Ape.psas.get();
if (response.status === 500) {
if (isLocalhost()) {
Notifications.addBanner(