You've already forked AstralRinth
forked from didirus/AstralRinth
Merge commit 'daf699911104207a477751916b36a371ee8f7e38' into feature-clean
This commit is contained in:
@@ -30,6 +30,7 @@ export const DEFAULT_FEATURE_FLAGS = validateValues({
|
||||
newProjectCards: false,
|
||||
projectBackground: false,
|
||||
searchBackground: false,
|
||||
advancedDebugInfo: false,
|
||||
// advancedRendering: true,
|
||||
// externalLinksNewTab: true,
|
||||
// notUsingBlockers: false,
|
||||
|
||||
@@ -10,6 +10,7 @@ interface PyroFetchOptions {
|
||||
token?: string;
|
||||
};
|
||||
retry?: boolean;
|
||||
bypassAuth?: boolean;
|
||||
}
|
||||
|
||||
export class PyroFetchError extends Error {
|
||||
@@ -28,7 +29,7 @@ export async function usePyroFetch<T>(path: string, options: PyroFetchOptions =
|
||||
const auth = await useAuth();
|
||||
const authToken = auth.value?.token;
|
||||
|
||||
if (!authToken) {
|
||||
if (!authToken && !options.bypassAuth) {
|
||||
throw new PyroFetchError("Cannot pyrofetch without auth", 10000);
|
||||
}
|
||||
|
||||
@@ -52,9 +53,15 @@ export async function usePyroFetch<T>(path: string, options: PyroFetchOptions =
|
||||
|
||||
type HeadersRecord = Record<string, string>;
|
||||
|
||||
const authHeader: HeadersRecord = options.bypassAuth
|
||||
? {}
|
||||
: {
|
||||
Authorization: `Bearer ${override?.token ?? authToken}`,
|
||||
"Access-Control-Allow-Headers": "Authorization",
|
||||
};
|
||||
|
||||
const headers: HeadersRecord = {
|
||||
Authorization: `Bearer ${override?.token ?? authToken}`,
|
||||
"Access-Control-Allow-Headers": "Authorization",
|
||||
...authHeader,
|
||||
"User-Agent": "Pyro/1.0 (https://pyro.host)",
|
||||
Vary: "Accept, Origin",
|
||||
"Content-Type": contentType,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// usePyroServer is a composable that interfaces with the REDACTED API to get data and control the users server
|
||||
import { $fetch, FetchError } from "ofetch";
|
||||
import type { ServerNotice } from "@modrinth/utils";
|
||||
import type { WSBackupState, WSBackupTask } from "~/types/servers.ts";
|
||||
|
||||
interface PyroFetchOptions {
|
||||
method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
||||
@@ -192,7 +194,7 @@ async function PyroFetch<T>(
|
||||
throw lastError || new Error("Maximum retry attempts reached");
|
||||
}
|
||||
|
||||
const internalServerRefrence = ref<any>(null);
|
||||
const internalServerReference = ref<any>(null);
|
||||
|
||||
interface License {
|
||||
id: string;
|
||||
@@ -289,6 +291,11 @@ interface General {
|
||||
sftp_password: string;
|
||||
sftp_host: string;
|
||||
datacenter?: string;
|
||||
notices?: ServerNotice[];
|
||||
node: {
|
||||
token: string;
|
||||
instance: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface Allocation {
|
||||
@@ -315,12 +322,20 @@ export interface Mod {
|
||||
installing: boolean;
|
||||
}
|
||||
|
||||
interface Backup {
|
||||
export interface Backup {
|
||||
id: string;
|
||||
name: string;
|
||||
created_at: string;
|
||||
ongoing: boolean;
|
||||
locked: boolean;
|
||||
automated: boolean;
|
||||
interrupted: boolean;
|
||||
ongoing: boolean;
|
||||
task: {
|
||||
[K in WSBackupTask]?: {
|
||||
progress: number;
|
||||
state: WSBackupState;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
interface AutoBackupSettings {
|
||||
@@ -368,7 +383,7 @@ const constructServerProperties = (properties: any): string => {
|
||||
|
||||
const processImage = async (iconUrl: string | undefined) => {
|
||||
const sharedImage = useState<string | undefined>(
|
||||
`server-icon-${internalServerRefrence.value.serverId}`,
|
||||
`server-icon-${internalServerReference.value.serverId}`,
|
||||
);
|
||||
|
||||
if (sharedImage.value) {
|
||||
@@ -376,7 +391,7 @@ const processImage = async (iconUrl: string | undefined) => {
|
||||
}
|
||||
|
||||
try {
|
||||
const auth = await PyroFetch<JWTAuth>(`servers/${internalServerRefrence.value.serverId}/fs`);
|
||||
const auth = await PyroFetch<JWTAuth>(`servers/${internalServerReference.value.serverId}/fs`);
|
||||
try {
|
||||
const fileData = await PyroFetch(`/download?path=/server-icon-original.png`, {
|
||||
override: auth,
|
||||
@@ -463,13 +478,13 @@ const processImage = async (iconUrl: string | undefined) => {
|
||||
|
||||
const sendPowerAction = async (action: string) => {
|
||||
try {
|
||||
await PyroFetch(`servers/${internalServerRefrence.value.serverId}/power`, {
|
||||
await PyroFetch(`servers/${internalServerReference.value.serverId}/power`, {
|
||||
method: "POST",
|
||||
body: { action },
|
||||
});
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
await internalServerRefrence.value.refresh();
|
||||
await internalServerReference.value.refresh();
|
||||
} catch (error) {
|
||||
console.error("Error changing power state:", error);
|
||||
throw error;
|
||||
@@ -478,7 +493,7 @@ const sendPowerAction = async (action: string) => {
|
||||
|
||||
const updateName = async (newName: string) => {
|
||||
try {
|
||||
await PyroFetch(`servers/${internalServerRefrence.value.serverId}/name`, {
|
||||
await PyroFetch(`servers/${internalServerReference.value.serverId}/name`, {
|
||||
method: "POST",
|
||||
body: { name: newName },
|
||||
});
|
||||
@@ -522,7 +537,7 @@ const reinstallFromMrpack = async (mrpack: File, hardReset: boolean = false) =>
|
||||
const hardResetParam = hardReset ? "true" : "false";
|
||||
try {
|
||||
const auth = await PyroFetch<JWTAuth>(
|
||||
`servers/${internalServerRefrence.value.serverId}/reinstallFromMrpack`,
|
||||
`servers/${internalServerReference.value.serverId}/reinstallFromMrpack`,
|
||||
);
|
||||
|
||||
const formData = new FormData();
|
||||
@@ -551,7 +566,7 @@ const reinstallFromMrpack = async (mrpack: File, hardReset: boolean = false) =>
|
||||
|
||||
const suspendServer = async (status: boolean) => {
|
||||
try {
|
||||
await PyroFetch(`servers/${internalServerRefrence.value.serverId}/suspend`, {
|
||||
await PyroFetch(`servers/${internalServerReference.value.serverId}/suspend`, {
|
||||
method: "POST",
|
||||
body: { suspended: status },
|
||||
});
|
||||
@@ -563,7 +578,7 @@ const suspendServer = async (status: boolean) => {
|
||||
|
||||
const fetchConfigFile = async (fileName: string) => {
|
||||
try {
|
||||
return await PyroFetch(`servers/${internalServerRefrence.value.serverId}/config/${fileName}`);
|
||||
return await PyroFetch(`servers/${internalServerReference.value.serverId}/config/${fileName}`);
|
||||
} catch (error) {
|
||||
console.error("Error fetching config file:", error);
|
||||
throw error;
|
||||
@@ -594,7 +609,7 @@ const setMotd = async (motd: string) => {
|
||||
const newProps = constructServerProperties(props);
|
||||
const octetStream = new Blob([newProps], { type: "application/octet-stream" });
|
||||
const auth = await await PyroFetch<JWTAuth>(
|
||||
`servers/${internalServerRefrence.value.serverId}/fs`,
|
||||
`servers/${internalServerReference.value.serverId}/fs`,
|
||||
);
|
||||
|
||||
return await PyroFetch(`/update?path=/server.properties`, {
|
||||
@@ -613,7 +628,7 @@ const setMotd = async (motd: string) => {
|
||||
|
||||
const installContent = async (contentType: ContentType, projectId: string, versionId: string) => {
|
||||
try {
|
||||
await PyroFetch(`servers/${internalServerRefrence.value.serverId}/mods`, {
|
||||
await PyroFetch(`servers/${internalServerReference.value.serverId}/mods`, {
|
||||
method: "POST",
|
||||
body: {
|
||||
rinth_ids: { project_id: projectId, version_id: versionId },
|
||||
@@ -628,7 +643,7 @@ const installContent = async (contentType: ContentType, projectId: string, versi
|
||||
|
||||
const removeContent = async (path: string) => {
|
||||
try {
|
||||
await PyroFetch(`servers/${internalServerRefrence.value.serverId}/deleteMod`, {
|
||||
await PyroFetch(`servers/${internalServerReference.value.serverId}/deleteMod`, {
|
||||
method: "POST",
|
||||
body: {
|
||||
path,
|
||||
@@ -642,7 +657,7 @@ const removeContent = async (path: string) => {
|
||||
|
||||
const reinstallContent = async (replace: string, projectId: string, versionId: string) => {
|
||||
try {
|
||||
await PyroFetch(`servers/${internalServerRefrence.value.serverId}/mods/update`, {
|
||||
await PyroFetch(`servers/${internalServerReference.value.serverId}/mods/update`, {
|
||||
method: "POST",
|
||||
body: { replace, project_id: projectId, version_id: versionId },
|
||||
});
|
||||
@@ -657,13 +672,13 @@ const reinstallContent = async (replace: string, projectId: string, versionId: s
|
||||
const createBackup = async (backupName: string) => {
|
||||
try {
|
||||
const response = await PyroFetch<{ id: string }>(
|
||||
`servers/${internalServerRefrence.value.serverId}/backups`,
|
||||
`servers/${internalServerReference.value.serverId}/backups`,
|
||||
{
|
||||
method: "POST",
|
||||
body: { name: backupName },
|
||||
},
|
||||
);
|
||||
await internalServerRefrence.value.refresh(["backups"]);
|
||||
await internalServerReference.value.refresh(["backups"]);
|
||||
return response.id;
|
||||
} catch (error) {
|
||||
console.error("Error creating backup:", error);
|
||||
@@ -673,11 +688,14 @@ const createBackup = async (backupName: string) => {
|
||||
|
||||
const renameBackup = async (backupId: string, newName: string) => {
|
||||
try {
|
||||
await PyroFetch(`servers/${internalServerRefrence.value.serverId}/backups/${backupId}/rename`, {
|
||||
method: "POST",
|
||||
body: { name: newName },
|
||||
});
|
||||
await internalServerRefrence.value.refresh(["backups"]);
|
||||
await PyroFetch(
|
||||
`servers/${internalServerReference.value.serverId}/backups/${backupId}/rename`,
|
||||
{
|
||||
method: "POST",
|
||||
body: { name: newName },
|
||||
},
|
||||
);
|
||||
await internalServerReference.value.refresh(["backups"]);
|
||||
} catch (error) {
|
||||
console.error("Error renaming backup:", error);
|
||||
throw error;
|
||||
@@ -686,10 +704,10 @@ const renameBackup = async (backupId: string, newName: string) => {
|
||||
|
||||
const deleteBackup = async (backupId: string) => {
|
||||
try {
|
||||
await PyroFetch(`servers/${internalServerRefrence.value.serverId}/backups/${backupId}`, {
|
||||
await PyroFetch(`servers/${internalServerReference.value.serverId}/backups/${backupId}`, {
|
||||
method: "DELETE",
|
||||
});
|
||||
await internalServerRefrence.value.refresh(["backups"]);
|
||||
await internalServerReference.value.refresh(["backups"]);
|
||||
} catch (error) {
|
||||
console.error("Error deleting backup:", error);
|
||||
throw error;
|
||||
@@ -699,30 +717,35 @@ const deleteBackup = async (backupId: string) => {
|
||||
const restoreBackup = async (backupId: string) => {
|
||||
try {
|
||||
await PyroFetch(
|
||||
`servers/${internalServerRefrence.value.serverId}/backups/${backupId}/restore`,
|
||||
`servers/${internalServerReference.value.serverId}/backups/${backupId}/restore`,
|
||||
{
|
||||
method: "POST",
|
||||
},
|
||||
);
|
||||
await internalServerRefrence.value.refresh(["backups"]);
|
||||
await internalServerReference.value.refresh(["backups"]);
|
||||
} catch (error) {
|
||||
console.error("Error restoring backup:", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
const downloadBackup = async (backupId: string) => {
|
||||
const prepareBackup = async (backupId: string) => {
|
||||
try {
|
||||
return await PyroFetch(`servers/${internalServerRefrence.value.serverId}/backups/${backupId}`);
|
||||
await PyroFetch(
|
||||
`servers/${internalServerReference.value.serverId}/backups/${backupId}/prepare-download`,
|
||||
{
|
||||
method: "POST",
|
||||
},
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("Error downloading backup:", error);
|
||||
console.error("Error preparing backup:", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
const updateAutoBackup = async (autoBackup: "enable" | "disable", interval: number) => {
|
||||
try {
|
||||
return await PyroFetch(`servers/${internalServerRefrence.value.serverId}/autobackup`, {
|
||||
return await PyroFetch(`servers/${internalServerReference.value.serverId}/autobackup`, {
|
||||
method: "POST",
|
||||
body: { set: autoBackup, interval },
|
||||
});
|
||||
@@ -734,7 +757,7 @@ const updateAutoBackup = async (autoBackup: "enable" | "disable", interval: numb
|
||||
|
||||
const getAutoBackup = async () => {
|
||||
try {
|
||||
return await PyroFetch(`servers/${internalServerRefrence.value.serverId}/autobackup`);
|
||||
return await PyroFetch(`servers/${internalServerReference.value.serverId}/autobackup`);
|
||||
} catch (error) {
|
||||
console.error("Error getting auto backup settings:", error);
|
||||
throw error;
|
||||
@@ -743,10 +766,10 @@ const getAutoBackup = async () => {
|
||||
|
||||
const lockBackup = async (backupId: string) => {
|
||||
try {
|
||||
await PyroFetch(`servers/${internalServerRefrence.value.serverId}/backups/${backupId}/lock`, {
|
||||
await PyroFetch(`servers/${internalServerReference.value.serverId}/backups/${backupId}/lock`, {
|
||||
method: "POST",
|
||||
});
|
||||
await internalServerRefrence.value.refresh(["backups"]);
|
||||
await internalServerReference.value.refresh(["backups"]);
|
||||
} catch (error) {
|
||||
console.error("Error locking backup:", error);
|
||||
throw error;
|
||||
@@ -755,22 +778,36 @@ const lockBackup = async (backupId: string) => {
|
||||
|
||||
const unlockBackup = async (backupId: string) => {
|
||||
try {
|
||||
await PyroFetch(`servers/${internalServerRefrence.value.serverId}/backups/${backupId}/unlock`, {
|
||||
method: "POST",
|
||||
});
|
||||
await internalServerRefrence.value.refresh(["backups"]);
|
||||
await PyroFetch(
|
||||
`servers/${internalServerReference.value.serverId}/backups/${backupId}/unlock`,
|
||||
{
|
||||
method: "POST",
|
||||
},
|
||||
);
|
||||
await internalServerReference.value.refresh(["backups"]);
|
||||
} catch (error) {
|
||||
console.error("Error unlocking backup:", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
const retryBackup = async (backupId: string) => {
|
||||
try {
|
||||
await PyroFetch(`servers/${internalServerReference.value.serverId}/backups/${backupId}/retry`, {
|
||||
method: "POST",
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error retrying backup:", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------ NETWORK ------------------ //
|
||||
|
||||
const reserveAllocation = async (name: string): Promise<Allocation> => {
|
||||
try {
|
||||
return await PyroFetch<Allocation>(
|
||||
`servers/${internalServerRefrence.value.serverId}/allocations?name=${name}`,
|
||||
`servers/${internalServerReference.value.serverId}/allocations?name=${name}`,
|
||||
{
|
||||
method: "POST",
|
||||
},
|
||||
@@ -784,7 +821,7 @@ const reserveAllocation = async (name: string): Promise<Allocation> => {
|
||||
const updateAllocation = async (port: number, name: string) => {
|
||||
try {
|
||||
await PyroFetch(
|
||||
`servers/${internalServerRefrence.value.serverId}/allocations/${port}?name=${name}`,
|
||||
`servers/${internalServerReference.value.serverId}/allocations/${port}?name=${name}`,
|
||||
{
|
||||
method: "PUT",
|
||||
},
|
||||
@@ -797,7 +834,7 @@ const updateAllocation = async (port: number, name: string) => {
|
||||
|
||||
const deleteAllocation = async (port: number) => {
|
||||
try {
|
||||
await PyroFetch(`servers/${internalServerRefrence.value.serverId}/allocations/${port}`, {
|
||||
await PyroFetch(`servers/${internalServerReference.value.serverId}/allocations/${port}`, {
|
||||
method: "DELETE",
|
||||
});
|
||||
} catch (error) {
|
||||
@@ -817,7 +854,7 @@ const checkSubdomainAvailability = async (subdomain: string): Promise<{ availabl
|
||||
|
||||
const changeSubdomain = async (subdomain: string) => {
|
||||
try {
|
||||
await PyroFetch(`servers/${internalServerRefrence.value.serverId}/subdomain`, {
|
||||
await PyroFetch(`servers/${internalServerReference.value.serverId}/subdomain`, {
|
||||
method: "POST",
|
||||
body: { subdomain },
|
||||
});
|
||||
@@ -835,7 +872,7 @@ const updateStartupSettings = async (
|
||||
jdkBuild: "corretto" | "temurin" | "graal",
|
||||
) => {
|
||||
try {
|
||||
await PyroFetch(`servers/${internalServerRefrence.value.serverId}/startup`, {
|
||||
await PyroFetch(`servers/${internalServerReference.value.serverId}/startup`, {
|
||||
method: "POST",
|
||||
body: {
|
||||
invocation: invocation || null,
|
||||
@@ -856,7 +893,7 @@ const retryWithAuth = async (requestFn: () => Promise<any>) => {
|
||||
return await requestFn();
|
||||
} catch (error) {
|
||||
if (error instanceof PyroServersFetchError && error.statusCode === 401) {
|
||||
await internalServerRefrence.value.refresh(["fs"]);
|
||||
await internalServerReference.value.refresh(["fs"]);
|
||||
return await requestFn();
|
||||
}
|
||||
|
||||
@@ -868,7 +905,7 @@ const listDirContents = (path: string, page: number, pageSize: number) => {
|
||||
return retryWithAuth(async () => {
|
||||
const encodedPath = encodeURIComponent(path);
|
||||
return await PyroFetch(`/list?path=${encodedPath}&page=${page}&page_size=${pageSize}`, {
|
||||
override: internalServerRefrence.value.fs.auth,
|
||||
override: internalServerReference.value.fs.auth,
|
||||
retry: false,
|
||||
});
|
||||
});
|
||||
@@ -880,7 +917,7 @@ const createFileOrFolder = (path: string, type: "file" | "directory") => {
|
||||
return await PyroFetch(`/create?path=${encodedPath}&type=${type}`, {
|
||||
method: "POST",
|
||||
contentType: "application/octet-stream",
|
||||
override: internalServerRefrence.value.fs.auth,
|
||||
override: internalServerReference.value.fs.auth,
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -923,9 +960,12 @@ const uploadFile = (path: string, file: File) => {
|
||||
|
||||
xhr.open(
|
||||
"POST",
|
||||
`https://${internalServerRefrence.value.fs.auth.url}/create?path=${encodedPath}&type=file`,
|
||||
`https://${internalServerReference.value.fs.auth.url}/create?path=${encodedPath}&type=file`,
|
||||
);
|
||||
xhr.setRequestHeader(
|
||||
"Authorization",
|
||||
`Bearer ${internalServerReference.value.fs.auth.token}`,
|
||||
);
|
||||
xhr.setRequestHeader("Authorization", `Bearer ${internalServerRefrence.value.fs.auth.token}`);
|
||||
xhr.setRequestHeader("Content-Type", "application/octet-stream");
|
||||
xhr.send(file);
|
||||
|
||||
@@ -955,7 +995,7 @@ const renameFileOrFolder = (path: string, name: string) => {
|
||||
return retryWithAuth(async () => {
|
||||
await PyroFetch(`/move`, {
|
||||
method: "POST",
|
||||
override: internalServerRefrence.value.fs.auth,
|
||||
override: internalServerReference.value.fs.auth,
|
||||
body: {
|
||||
source: path,
|
||||
destination: pathName,
|
||||
@@ -972,7 +1012,7 @@ const updateFile = (path: string, content: string) => {
|
||||
method: "PUT",
|
||||
contentType: "application/octet-stream",
|
||||
body: octetStream,
|
||||
override: internalServerRefrence.value.fs.auth,
|
||||
override: internalServerReference.value.fs.auth,
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -1002,7 +1042,7 @@ const moveFileOrFolder = (path: string, newPath: string) => {
|
||||
|
||||
return await PyroFetch(`/move`, {
|
||||
method: "POST",
|
||||
override: internalServerRefrence.value.fs.auth,
|
||||
override: internalServerReference.value.fs.auth,
|
||||
body: {
|
||||
source: path,
|
||||
destination: newPath,
|
||||
@@ -1016,7 +1056,7 @@ const deleteFileOrFolder = (path: string, recursive: boolean) => {
|
||||
return retryWithAuth(async () => {
|
||||
return await PyroFetch(`/delete?path=${encodedPath}&recursive=${recursive}`, {
|
||||
method: "DELETE",
|
||||
override: internalServerRefrence.value.fs.auth,
|
||||
override: internalServerReference.value.fs.auth,
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -1025,7 +1065,7 @@ const downloadFile = (path: string, raw?: boolean) => {
|
||||
return retryWithAuth(async () => {
|
||||
const encodedPath = encodeURIComponent(path);
|
||||
const fileData = await PyroFetch(`/download?path=${encodedPath}`, {
|
||||
override: internalServerRefrence.value.fs.auth,
|
||||
override: internalServerReference.value.fs.auth,
|
||||
});
|
||||
|
||||
if (fileData instanceof Blob) {
|
||||
@@ -1137,11 +1177,12 @@ const modules: any = {
|
||||
rename: renameBackup,
|
||||
delete: deleteBackup,
|
||||
restore: restoreBackup,
|
||||
download: downloadBackup,
|
||||
prepare: prepareBackup,
|
||||
updateAutoBackup,
|
||||
getAutoBackup,
|
||||
lock: lockBackup,
|
||||
unlock: unlockBackup,
|
||||
retry: retryBackup,
|
||||
},
|
||||
network: {
|
||||
get: async (serverId: string) => {
|
||||
@@ -1382,6 +1423,12 @@ type BackupFunctions = {
|
||||
*/
|
||||
download: (backupId: string) => Promise<void>;
|
||||
|
||||
/**
|
||||
* Prepare a backup for the server.
|
||||
* @param backupId - The ID of the backup.
|
||||
*/
|
||||
prepare: (backupId: string) => Promise<void>;
|
||||
|
||||
/**
|
||||
* Updates the auto backup settings of the server.
|
||||
* @param autoBackup - Whether to enable auto backup.
|
||||
@@ -1405,6 +1452,12 @@ type BackupFunctions = {
|
||||
* @param backupId - The ID of the backup.
|
||||
*/
|
||||
unlock: (backupId: string) => Promise<void>;
|
||||
|
||||
/**
|
||||
* Retries a failed backup for the server.
|
||||
* @param backupId - The ID of the backup.
|
||||
*/
|
||||
retry: (backupId: string) => Promise<void>;
|
||||
};
|
||||
|
||||
type NetworkFunctions = {
|
||||
@@ -1702,7 +1755,7 @@ export const usePyroServer = async (serverId: string, includedModules: avaliable
|
||||
server[module] = modules[module];
|
||||
});
|
||||
|
||||
internalServerRefrence.value = server;
|
||||
internalServerReference.value = server;
|
||||
await server.refresh(initialModules);
|
||||
|
||||
if (deferredModules.length > 0) {
|
||||
|
||||
Reference in New Issue
Block a user