2023-06-14 12:20:40 +00:00
|
|
|
import { LemmyHttp } from "lemmy-js-client";
|
|
|
|
import { getHttpBase } from "../../shared/env";
|
2023-06-21 22:28:24 +00:00
|
|
|
import { toast } from "../../shared/toast";
|
2023-06-22 00:54:35 +00:00
|
|
|
import { I18NextService } from "./I18NextService";
|
2023-06-14 12:20:40 +00:00
|
|
|
|
|
|
|
type EmptyRequestState = {
|
|
|
|
state: "empty";
|
|
|
|
};
|
|
|
|
|
|
|
|
type LoadingRequestState = {
|
|
|
|
state: "loading";
|
|
|
|
};
|
|
|
|
|
2023-06-16 02:08:14 +00:00
|
|
|
export type FailedRequestState = {
|
2023-06-14 12:20:40 +00:00
|
|
|
state: "failed";
|
|
|
|
msg: string;
|
|
|
|
};
|
|
|
|
|
|
|
|
type SuccessRequestState<T> = {
|
|
|
|
state: "success";
|
|
|
|
data: T;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Shows the state of an API request.
|
|
|
|
*
|
|
|
|
* Can be empty, loading, failed, or success
|
|
|
|
*/
|
|
|
|
export type RequestState<T> =
|
|
|
|
| EmptyRequestState
|
|
|
|
| LoadingRequestState
|
|
|
|
| FailedRequestState
|
|
|
|
| SuccessRequestState<T>;
|
|
|
|
|
|
|
|
export type WrappedLemmyHttp = {
|
|
|
|
[K in keyof LemmyHttp]: LemmyHttp[K] extends (...args: any[]) => any
|
|
|
|
? ReturnType<LemmyHttp[K]> extends Promise<infer U>
|
|
|
|
? (...args: Parameters<LemmyHttp[K]>) => Promise<RequestState<U>>
|
|
|
|
: (
|
|
|
|
...args: Parameters<LemmyHttp[K]>
|
|
|
|
) => Promise<RequestState<LemmyHttp[K]>>
|
|
|
|
: LemmyHttp[K];
|
|
|
|
};
|
|
|
|
|
|
|
|
class WrappedLemmyHttpClient {
|
|
|
|
#client: LemmyHttp;
|
|
|
|
|
|
|
|
constructor(client: LemmyHttp) {
|
|
|
|
this.#client = client;
|
|
|
|
|
|
|
|
for (const key of Object.getOwnPropertyNames(
|
|
|
|
Object.getPrototypeOf(this.#client)
|
|
|
|
)) {
|
|
|
|
if (key !== "constructor") {
|
|
|
|
WrappedLemmyHttpClient.prototype[key] = async (...args) => {
|
|
|
|
try {
|
|
|
|
const res = await this.#client[key](...args);
|
|
|
|
|
|
|
|
return {
|
|
|
|
data: res,
|
2023-06-16 02:08:14 +00:00
|
|
|
state: !(res === undefined || res === null) ? "success" : "empty",
|
2023-06-14 12:20:40 +00:00
|
|
|
};
|
|
|
|
} catch (error) {
|
|
|
|
console.error(`API error: ${error}`);
|
2023-06-22 00:54:35 +00:00
|
|
|
toast(I18NextService.i18n.t(error), "danger");
|
2023-06-14 12:20:40 +00:00
|
|
|
return {
|
|
|
|
state: "failed",
|
|
|
|
msg: error,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function wrapClient(client: LemmyHttp) {
|
|
|
|
return new WrappedLemmyHttpClient(client) as unknown as WrappedLemmyHttp; // unfortunately, this verbose cast is necessary
|
|
|
|
}
|
|
|
|
|
|
|
|
export class HttpService {
|
|
|
|
static #_instance: HttpService;
|
|
|
|
#client: WrappedLemmyHttp;
|
|
|
|
|
|
|
|
private constructor() {
|
|
|
|
this.#client = wrapClient(new LemmyHttp(getHttpBase()));
|
|
|
|
}
|
|
|
|
|
|
|
|
static get #Instance() {
|
|
|
|
return this.#_instance ?? (this.#_instance = new this());
|
|
|
|
}
|
|
|
|
|
|
|
|
public static get client() {
|
|
|
|
return this.#Instance.#client;
|
|
|
|
}
|
|
|
|
}
|