[TS] Initial Typescript fix

This commit is contained in:
Dunemask 2024-04-06 20:38:10 -06:00
parent 8c15dd6752
commit 813295c857
36 changed files with 4285 additions and 1951 deletions

View file

@ -0,0 +1,15 @@
import { mclAuthenticatedApiRequest } from "@mcl/api/requests";
export const getServerBackups = (serverId: string) =>
mclAuthenticatedApiRequest({
subPath: "/s3/backups",
json: { id: serverId },
jsonify: true,
});
export const getBackupUrl = (serverId: string, backupPath: string) =>
mclAuthenticatedApiRequest({
subPath: "/s3/backup-url",
json: { id: serverId, backupPath },
jsonify: true,
});

View file

@ -0,0 +1,68 @@
import { mclAuthenticatedApiRequest } from "@mcl/api/requests";
// ===== API Requests =====
export const getServerFiles = (serverId: string, path: string) =>
mclAuthenticatedApiRequest({
subPath: "/files/list",
json: { id: serverId, path },
});
export const createServerFolder = (serverId: string, path: string) =>
mclAuthenticatedApiRequest({
subPath: "/files/folder",
json: { id: serverId, path },
});
export const uploadServerItem = (body:FormData) =>
mclAuthenticatedApiRequest({
subPath: "/files/upload",
body,
})
export const deleteServerItem = (
serverId: string,
path: string,
isDir: boolean,
) =>
mclAuthenticatedApiRequest({
subPath: "/files/item",
json: { id: serverId, path, isDir },
method: "DELETE",
});
export const moveServerItems = (
serverId: string,
files: string,
destination: string,
origin: string,
) =>
mclAuthenticatedApiRequest({
subPath: "/files/move",
json: { id: serverId, files, destination, origin },
});
export const previewServerItem = (serverId: string, path: string) =>
mclAuthenticatedApiRequest({
subPath: "/files/item",
json: { id: serverId, path },
}).then((res) => res.blob());
export const getServerItem = (serverId: string, name: string, path: string) =>
mclAuthenticatedApiRequest({
subPath: "/files/item",
json: { id: serverId, path },
})
.then((res) => res.blob())
.then((blob) => downloadBlob(blob, name));
async function downloadBlob(blob: Blob, name: string) {
const url = window.URL.createObjectURL(blob);
const a = document.createElement("a");
a.style.display = "none";
a.href = url;
a.download = name;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
}

View file

@ -0,0 +1,27 @@
import { useQuery } from "@tanstack/react-query";
import { mclAuthenticatedApiRequest } from "../requests";
// ===== API Requests =====
export const getSystemAvailable = () =>
mclAuthenticatedApiRequest({
subPath: "/system/available",
jsonify: true,
});
// ===== API Queries =====
export const useSystemAvailable = () =>
useQuery({
queryKey: ["system-available"],
queryFn: getSystemAvailable,
});
export const useVersionList = () =>
useQuery({
queryKey: ["minecraft-versions"],
queryFn: () =>
fetch(
"https://piston-meta.mojang.com/mc/game/version_manifest.json",
).then((r) => r.json()),
});

View file

@ -0,0 +1,122 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { mclAuthenticatedApiRequest, useMutator } from "../requests";
// ===== API Utils =====
const useInstanceControl = (apiRequest: (args: any) => Promise<any>) =>
useMutator(apiRequest, ["server-instances"]);
const useListControl = (apiRequest: (args: any) => Promise<any>) =>
useMutator(apiRequest, ["server-list"]);
// ===== API Requests =====
export const getServerList = () =>
mclAuthenticatedApiRequest({
subPath: "/server/path",
jsonify: true,
});
export const getServerInstances = () =>
mclAuthenticatedApiRequest({
subPath: "/server/instances",
jsonify: true,
});
export const getServerMetrics = (serverId: string) =>
mclAuthenticatedApiRequest({
subPath: "/server/metrics",
json: { id: serverId },
jsonify: true,
});
export const getServerStatus = (serverId: string) =>
mclAuthenticatedApiRequest({
subPath: "/server/status",
json: { id: serverId },
jsonify: true,
});
export const requestServerStart = (serverId: string) =>
mclAuthenticatedApiRequest({
subPath: "/server/start",
json: { id: serverId },
});
export const requestServerStop = (serverId: string) =>
mclAuthenticatedApiRequest({
subPath: "/server/stop",
json: { id: serverId },
});
export const requestServerDelete = (serverId: string) =>
mclAuthenticatedApiRequest({
subPath: "/server/delete",
json: { id: serverId },
method: "DELETE",
});
export const requestServerCreate = (serverSpec: any) =>
mclAuthenticatedApiRequest({
subPath: "/server/create",
json: serverSpec,
});
export const requestServerModify = (serverSpec: any) =>
mclAuthenticatedApiRequest({
subPath: "/server/modify",
json: serverSpec,
});
export const getServerBlueprint = (serverId: string) =>
mclAuthenticatedApiRequest({
subPath: "/server/blueprint",
json: { id: serverId },
jsonify: true
})
// ===== API Queries =====
export const useServerList = () =>
useQuery({ queryKey: ["server-list"], queryFn: getServerList });
export const useServerInstances = () =>
useQuery({
queryKey: ["server-instances"],
queryFn: getServerInstances,
refetchInterval: 5000,
});
export const useServerMetrics = (serverId: string) =>
useQuery({
queryKey: [`server-metrics-${serverId}`],
queryFn: () => getServerMetrics(serverId),
refetchInterval: 10000,
});
export const useServerStatus = (serverId: string) =>
useQuery({
queryKey: [`server-status-${serverId}`],
queryFn: () => getServerStatus(serverId),
});
export const useServerStart = (serverId: string) =>
useInstanceControl(() => requestServerStart(serverId));
export const useServerStop = (serverId: string) =>
useInstanceControl(() => requestServerStop(serverId));
export const useServerDelete = (serverId: string) =>
useInstanceControl(() => requestServerDelete(serverId));
export const useServerCreate = (spec: any) =>
useListControl(() => requestServerCreate(spec));
export const useServerModify = (spec: any) =>
useListControl(() => requestServerModify(spec));
export const useBlueprint = (serverId: string) =>
useQuery({
queryKey: [`server-blueprint-${serverId}`],
queryFn: ()=>getServerBlueprint(serverId),
})

56
src/util/api/requests.ts Normal file
View file

@ -0,0 +1,56 @@
import {
useMutation,
useQueryClient,
} from "@tanstack/react-query";
import { cairoAuthHeader } from "./auth";
declare interface ApiRequestArgs {
subPath: string;
body?: any | undefined;
json?: object | undefined;
method?: string;
jsonify?: boolean;
extraHeaders?: object;
handleErrors?: boolean;
}
async function apiRequest(apiRequestArgs: ApiRequestArgs) {
const { subPath, json, body, method, jsonify, extraHeaders, handleErrors } =
apiRequestArgs;
const headers = extraHeaders ?? {};
const requestMethod = method ?? !!json ? "POST" : "GET";
const requestBody = body ?? !!json ? JSON.stringify(json) : undefined;
if (!!json) headers["Content-Type"] = "application/json";
return fetch(`/api${subPath}`, {
method: requestMethod,
body: requestBody
}).then((res) => {
if (res.status >= 300 && handleErrors) throw Error(res.statusText);
if (jsonify) return res.json();
return res;
});
}
export async function mclAuthenticatedApiRequest(
apiRequestArgs: ApiRequestArgs,
) {
const extraHeaders = apiRequestArgs.extraHeaders ?? {};
const authHeaders = cairoAuthHeader();
apiRequestArgs.extraHeaders = { ...extraHeaders, ...authHeaders };
return apiRequest(apiRequestArgs);
}
export async function mclApiRequest(apiRequestArgs: ApiRequestArgs) {
return apiRequest(apiRequestArgs);
}
export const useMutator = async (
apiRequest: (args: any) => Promise<any>,
invalidate: string[],
) => {
const qc = useQueryClient();
useMutation({
mutationFn: apiRequest,
onSuccess: () => qc.invalidateQueries({ queryKey: invalidate }),
});
};

View file

@ -1,145 +0,0 @@
// @ts-nocheck
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { cairoAuthHeader } from "@mcl/util/auth.js";
const fetchApi = (subPath) => async () =>
fetch(`/api${subPath}`, { headers: cairoAuthHeader() }).then((res) =>
res.json(),
);
const fetchApiCore = async (subPath, json, method = "POST", jsonify = false) =>
fetch(`/api${subPath}`, {
method,
headers: {
"Content-Type": "application/json",
...cairoAuthHeader(),
},
body: JSON.stringify(json),
}).then((res) => (jsonify ? res.json() : res));
const fetchApiPost = (subPath, json) => async () =>
fetch(`/api${subPath}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
...cairoAuthHeader(),
},
body: JSON.stringify(json),
}).then((res) => res.json());
export const useServerStatus = (serverId) =>
useQuery({
queryKey: [`server-status-${serverId}`],
queryFn: fetchApiPost("/server/status", { id: serverId }),
});
export const useServerMetrics = (serverId) =>
useQuery({
queryKey: [`server-metrics-${serverId}`],
queryFn: fetchApiPost("/server/metrics", { id: serverId }),
refetchInterval: 10000,
});
export const useStartServer = (serverId) =>
postJsonApi("/server/start", { id: serverId }, "server-instances");
export const useStopServer = (serverId) =>
postJsonApi("/server/stop", { id: serverId }, "server-instances");
export const useDeleteServer = (serverId) =>
postJsonApi("/server/delete", { id: serverId }, "server-instances", "DELETE");
export const useCreateServer = (spec) =>
postJsonApi("/server/create", spec, "server-list");
export const useModifyServer = (spec) =>
postJsonApi("/server/modify", spec, "server-list");
export const useGetServer = (serverId) =>
useQuery({
queryKey: [`server-blueprint-${serverId}`],
queryFn: fetchApiPost("/server/blueprint", { id: serverId }),
});
export const getServerBackups = (serverId) =>
fetchApiCore("/s3/backups", { id: serverId }, "POST", true);
export const getBackupUrl = (serverId, backupPath) =>
fetchApiCore("/s3/backup-url", { id: serverId, backupPath }, "POST", true);
export const getServerFiles = async (serverId, path) =>
fetchApiCore("/files/list", { id: serverId, path }, "POST", true);
export const createServerFolder = async (serverId, path) =>
fetchApiCore("/files/folder", {
id: serverId,
path,
});
export const deleteServerItem = async (serverId, path, isDir) =>
fetchApiCore("/files/item", { id: serverId, path, isDir }, "DELETE");
export const moveServerItems = async (serverId, files, destination, origin) =>
fetchApiCore(
"/files/move",
{ id: serverId, files, destination, origin },
"POST",
);
export async function previewServerItem(serverId, path) {
const resp = await fetchApiCore("/files/item", { id: serverId, path });
if (resp.status !== 200) return console.log("AHHHH");
const blob = await resp.blob();
return blob;
}
export const getServerItem = async (serverId, name, path) =>
fetchApiCore("/files/item", { id: serverId, path })
.then((resp) =>
resp.status === 200
? resp.blob()
: Promise.reject("something went wrong"),
)
.then((blob) => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement("a");
a.style.display = "none";
a.href = url;
a.download = name;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
});
export const useInvalidator = () => {
const qc = useQueryClient();
return (q) => qc.invalidateQueries([q]);
};
export const useServerList = () =>
useQuery({ queryKey: ["server-list"], queryFn: fetchApi("/server/list") });
export const useServerInstances = () =>
useQuery({
queryKey: ["server-instances"],
queryFn: fetchApi("/server/instances"),
refetchInterval: 5000,
});
export const useSystemAvailable = () =>
useQuery({
queryKey: ["system-available"],
queryFn: fetchApi("/system/available"),
});
export const useVersionList = () =>
useQuery({
queryKey: ["minecraft-versions"],
queryFn: () =>
fetch(
"https://piston-meta.mojang.com/mc/game/version_manifest.json",
).then((r) => r.json()),
});
const postJsonApi = (subPath, body, invalidate, method = "POST") => {
const qc = useQueryClient();
return async () => {
const res = await fetch(`/api${subPath}`, {
method,
headers: {
"Content-Type": "application/json",
...cairoAuthHeader(),
},
body: JSON.stringify(body),
});
if (invalidate) qc.invalidateQueries([invalidate]);
};
};