Merge branch 'oneclient/main' of https://github.com/Polyfrost/OneLauncher into refactor/frontend
This commit is contained in:
commit
a3e80ffc77
31 changed files with 448 additions and 1120 deletions
|
|
@ -16,7 +16,8 @@
|
|||
"build": "tauri build",
|
||||
"dev": "tauri dev",
|
||||
"tauri": "tauri",
|
||||
"tauri-ext": "pnpm --filter @onelauncher/scripts -- tauri"
|
||||
"tauri-ext": "pnpm --filter @onelauncher/scripts -- tauri",
|
||||
"cargo": "cargo"
|
||||
},
|
||||
"dependencies": {
|
||||
"@oneclient/frontend": "workspace:*"
|
||||
|
|
|
|||
|
|
@ -1,112 +0,0 @@
|
|||
// This file has been generated by Specta. DO NOT EDIT.
|
||||
|
||||
import type { InferCommandOutput } from 'taurpc';
|
||||
import { createTauRPCProxy as createProxy } from 'taurpc';
|
||||
|
||||
type TAURI_CHANNEL<T> = (response: T) => void;
|
||||
|
||||
export type ClusterError = { InvalidVersion: string } | 'MissingJavaVersion' | 'ClusterDownloading' | 'ClusterAlreadyRunning';
|
||||
|
||||
export type ClusterStage = 'notready' | 'downloading' | 'repairing' | 'ready';
|
||||
|
||||
export interface CreateCluster { name: string; mc_version: string; mc_loader: GameLoader; mc_loader_version: string | null; icon: Icon | null }
|
||||
|
||||
export type CryptoError = { InvalidHash: { algorithm: HashAlgorithm; expected: string; actual: string } } | 'InvalidAlgorithm';
|
||||
|
||||
export type DaoError = 'NotFound' | 'AlreadyExists' | { InvalidValue: [string, string] };
|
||||
|
||||
export type DirectoryError = 'BaseDir';
|
||||
|
||||
export type DiscordError = 'MissingClientId' | 'ConnectError';
|
||||
|
||||
export type GameLoader = 'vanilla' | 'forge' | 'neoforge' | 'quilt' | 'fabric' | 'legacyfabric';
|
||||
|
||||
export type HashAlgorithm = 'Sha1' | 'Sha256' | 'Md5';
|
||||
|
||||
/**
|
||||
* A wrapper around generic and unhelpful [`std::io::Error`] messages.
|
||||
*/
|
||||
export type IOError = { InvalidAbsolutePath: string } | { IOErrorWrapper: { path: string } } | 'IOError' | 'DeserializeError' | 'AsyncZipError';
|
||||
|
||||
export type Icon = string;
|
||||
|
||||
export type IncompatiblePackageType = 'McVersion' | 'Loader';
|
||||
|
||||
export type IngressError = 'NotFound';
|
||||
|
||||
export interface IngressPayload { id: string; message: string; ingress_type: IngressType; percent: number | null; total: number }
|
||||
|
||||
export type IngressType = { Download: { file_name: string } } | 'JavaPrepare' | 'JavaCheck' | 'JavaLocate' | 'MinecraftDownload' | { PrepareCluster: { cluster_name: string } };
|
||||
|
||||
export type JavaError = { ParseVersion: [string] } | 'Execute' | 'MissingJava';
|
||||
|
||||
export type LauncherError = { type: 'DirError'; data: DirectoryError } | { type: 'IOError'; data: IOError } | { type: 'IngressError'; data: IngressError } | { type: 'JavaError'; data: JavaError } | { type: 'CryptoError'; data: CryptoError } | { type: 'DiscordError'; data: DiscordError } | { type: 'MetadataError'; data: MetadataError } | { type: 'ClusterError'; data: ClusterError } | { type: 'MinecraftAuthError'; data: MinecraftAuthError } | { type: 'ProcessError'; data: ProcessError } | { type: 'PackageError'; data: PackageError } | { type: 'DaoError'; data: DaoError } | { type: 'SerdeError' } | { type: 'AnyhowError' } | { type: 'DbError' } | { type: 'ReqwestError' } | { type: 'InterpulseError' } | { type: 'RegexError' } | { type: 'SemaphoreError' } | { type: 'UrlError' } | { type: 'TauriError' };
|
||||
|
||||
export type MessageLevel = 'Info' | 'Warn' | 'Error';
|
||||
|
||||
export interface MessagePayload { level: MessageLevel; message: string }
|
||||
|
||||
export type MetadataError = 'FetchError' | { NotModdedManifest: GameLoader } | { NotVanillaManifest: GameLoader } | 'ParseError' | 'NoMatchingLoader' | 'NoMatchingVersion';
|
||||
|
||||
/**
|
||||
* Wrapper around all `Error`s that can occur during the Microsoft authentication process.
|
||||
*/
|
||||
export type MinecraftAuthError = 'PublicKeyReading' | 'PKCS8Error' | { SerializeError: { step: MinecraftAuthStep } } | { DeserializeError: { step: MinecraftAuthStep; raw: string } } | { RequestError: { step: MinecraftAuthStep } } | { SigningError: { step: MinecraftAuthStep } } | 'HashError' | 'SessionIdError';
|
||||
|
||||
/**
|
||||
* An ordered list of all MSA authentication steps.
|
||||
*/
|
||||
export type MinecraftAuthStep = 'DeviceToken' | 'SisuAuthenicate' | 'OAuthToken' | 'RefreshOAuthToken' | 'SisuAuthorize' | 'XstsAuthorize' | 'MinecraftToken' | 'MinecraftEntitlements' | 'MinecraftProfile';
|
||||
|
||||
/**
|
||||
* A structure of all needed Minecraft credentials for logging in and account management.
|
||||
*/
|
||||
export interface MinecraftCredentials {
|
||||
/**
|
||||
* The uuid of the credentials.
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* The username of the Minecraft account.
|
||||
*/
|
||||
username: string;
|
||||
/**
|
||||
* The access token as a String.
|
||||
*/
|
||||
access_token: string;
|
||||
/**
|
||||
* The refresh token as a string for [`MinecraftState#refresh`].
|
||||
*/
|
||||
refresh_token: string;
|
||||
/**
|
||||
* The time that the access token expires as a [`DateTime<Utc>`].
|
||||
*/
|
||||
expires: string;
|
||||
|
||||
}
|
||||
|
||||
export interface Model { id: bigint; folder_name: string; stage: ClusterStage; created_at: string; group_id: bigint | null; name: string; mc_version: string; mc_loader: GameLoader; mc_loader_version: string | null; last_played: string | null; overall_played: bigint | null; icon_url: Icon | null; setting_profile_name: string | null; linked_pack_id: string | null; linked_pack_version: string | null }
|
||||
|
||||
export type PackageError = 'NoPrimaryFile' | 'IsModPack' | { Incompatible: IncompatiblePackageType };
|
||||
|
||||
export interface Process { pid: number; started_at: string; cluster_id: bigint; post_hook: string | null; account_id: string }
|
||||
|
||||
export type ProcessError = { HookUnsuccessful: number } | 'NoPid';
|
||||
|
||||
export type ProcessPayload = { type: 'Starting'; command: string } | { type: 'Started'; process: Process } | { type: 'Stopped'; pid: number; exit_code: number } | { type: 'Output'; pid: number; output: string };
|
||||
|
||||
export interface Resolution { width: number; height: number }
|
||||
|
||||
export interface SettingProfileModel { name: string; java_id: bigint | null; res: Resolution | null; force_fullscreen: boolean | null; mem_max: number | null; launch_args: string | null; launch_env: string | null; hook_pre: string | null; hook_wrapper: string | null; hook_post: string | null; os_extra: SettingsOsExtra | null }
|
||||
|
||||
export interface SettingsOsExtra { enable_gamemode: boolean | null }
|
||||
|
||||
const ARGS_MAP = { oneclient: '{"open_dev_tools":[],"return_error":[]}', core: '{"getClusters":[],"createCluster":["options"],"getGlobalProfile":[],"getClusterById":["id"],"openMsaLogin":[],"getUsers":[],"getDefaultUser":["fallback"],"setDefaultUser":["uuid"],"getUser":["uuid"],"getProfileOrDefault":["name"],"removeUser":["uuid"],"removeCluster":["id"],"launchCluster":["id","uuid"]}', events: '{"message":["event"],"process":["event"],"ingress":["event"]}' };
|
||||
export interface Router {
|
||||
events: { ingress: (event: IngressPayload) => Promise<void>; message: (event: MessagePayload) => Promise<void>; process: (event: ProcessPayload) => Promise<void> };
|
||||
core: { getClusters: () => Promise<Array<Model>>; getClusterById: (id: bigint) => Promise<Model | null>; removeCluster: (id: bigint) => Promise<null>; createCluster: (options: CreateCluster) => Promise<Model>; launchCluster: (id: bigint, uuid: string | null) => Promise<null>; getProfileOrDefault: (name: string | null) => Promise<SettingProfileModel>; getGlobalProfile: () => Promise<SettingProfileModel>; getUsers: () => Promise<Array<MinecraftCredentials>>; getUser: (uuid: string) => Promise<MinecraftCredentials | null>; removeUser: (uuid: string) => Promise<null>; getDefaultUser: (fallback: boolean | null) => Promise<MinecraftCredentials | null>; setDefaultUser: (uuid: string | null) => Promise<null>; openMsaLogin: () => Promise<MinecraftCredentials | null> };
|
||||
oneclient: { return_error: () => Promise<null>; open_dev_tools: () => Promise<void> };
|
||||
}
|
||||
|
||||
export type { InferCommandOutput };
|
||||
export const createTauRPCProxy = () => createProxy<Router>(ARGS_MAP);
|
||||
27
apps/oneclient/frontend/src/components/MyContext.tsx
Normal file
27
apps/oneclient/frontend/src/components/MyContext.tsx
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import type { Context } from 'react';
|
||||
import { createContext, useContext } from 'react';
|
||||
|
||||
const myContext = createContext(null) as Context<
|
||||
{
|
||||
text: string;
|
||||
} | null
|
||||
>;
|
||||
|
||||
export function MyContextProvider({ children, value }: {
|
||||
children: React.ReactNode;
|
||||
value: {
|
||||
text: string;
|
||||
} | null;
|
||||
}) {
|
||||
// eslint-disable-next-line react/no-context-provider -- ok
|
||||
return <myContext.Provider value={value}>{children}</myContext.Provider>;
|
||||
}
|
||||
|
||||
export default function useMyContext() {
|
||||
const context = useContext(myContext);
|
||||
|
||||
if (!context)
|
||||
throw new Error('useMyContext must be used within a MyContextProvider');
|
||||
|
||||
return context;
|
||||
}
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
/* eslint-disable */
|
||||
|
||||
// @ts-nocheck
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
|
||||
// This file was automatically generated by TanStack Router.
|
||||
// You should NOT make any changes in this file as it will be overwritten.
|
||||
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
|
||||
|
||||
// Import Routes
|
||||
|
||||
import { Route as rootRoute } from './routes/__root'
|
||||
import { Route as IndexImport } from './routes/index'
|
||||
|
||||
// Create/Update Routes
|
||||
|
||||
const IndexRoute = IndexImport.update({
|
||||
id: '/',
|
||||
path: '/',
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any)
|
||||
|
||||
// Populate the FileRoutesByPath interface
|
||||
|
||||
declare module '@tanstack/react-router' {
|
||||
interface FileRoutesByPath {
|
||||
'/': {
|
||||
id: '/'
|
||||
path: '/'
|
||||
fullPath: '/'
|
||||
preLoaderRoute: typeof IndexImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create and export the route tree
|
||||
|
||||
export interface FileRoutesByFullPath {
|
||||
'/': typeof IndexRoute
|
||||
}
|
||||
|
||||
export interface FileRoutesByTo {
|
||||
'/': typeof IndexRoute
|
||||
}
|
||||
|
||||
export interface FileRoutesById {
|
||||
__root__: typeof rootRoute
|
||||
'/': typeof IndexRoute
|
||||
}
|
||||
|
||||
export interface FileRouteTypes {
|
||||
fileRoutesByFullPath: FileRoutesByFullPath
|
||||
fullPaths: '/'
|
||||
fileRoutesByTo: FileRoutesByTo
|
||||
to: '/'
|
||||
id: '__root__' | '/'
|
||||
fileRoutesById: FileRoutesById
|
||||
}
|
||||
|
||||
export interface RootRouteChildren {
|
||||
IndexRoute: typeof IndexRoute
|
||||
}
|
||||
|
||||
const rootRouteChildren: RootRouteChildren = {
|
||||
IndexRoute: IndexRoute,
|
||||
}
|
||||
|
||||
export const routeTree = rootRoute
|
||||
._addFileChildren(rootRouteChildren)
|
||||
._addFileTypes<FileRouteTypes>()
|
||||
|
||||
/* ROUTE_MANIFEST_START
|
||||
{
|
||||
"routes": {
|
||||
"__root__": {
|
||||
"filePath": "__root.tsx",
|
||||
"children": [
|
||||
"/"
|
||||
]
|
||||
},
|
||||
"/": {
|
||||
"filePath": "index.tsx"
|
||||
}
|
||||
}
|
||||
}
|
||||
ROUTE_MANIFEST_END */
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import type { LauncherError } from '@/bindings.gen';
|
||||
import { bindings } from '@/main';
|
||||
import { Button } from '@onelauncher/common/components';
|
||||
import { createFileRoute } from '@tanstack/react-router';
|
||||
|
|
@ -16,15 +17,33 @@ function App() {
|
|||
// mc_loader_version: '11.15.1.2318',
|
||||
// });
|
||||
|
||||
await bindings.core.launchCluster(2 as unknown as bigint, null);
|
||||
try {
|
||||
// await bindings.core.launchCluster(9 as unknown as bigint, null);
|
||||
await bindings.core.removeCluster(9 as unknown as bigint);
|
||||
|
||||
const unlisten = await bindings.events.process.on((e) => {
|
||||
if (e.type === 'Output') { console.log(e.output); }
|
||||
else if (e.type === 'Stopped') {
|
||||
console.log(e.exit_code);
|
||||
unlisten();
|
||||
}
|
||||
});
|
||||
const unlisten = await bindings.events.process.on((e) => {
|
||||
if (e.type === 'Output') { console.log(e.output); }
|
||||
else if (e.type === 'Stopped') {
|
||||
console.log(e.exit_code);
|
||||
unlisten();
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (err: unknown) {
|
||||
let error = err as LauncherError;
|
||||
// console.log(error);
|
||||
// if (error.type === 'DaoError')
|
||||
// if (error.data.type === 'NotFound')
|
||||
// console.log(error.data.data);
|
||||
if (error.type === 'TauriError')
|
||||
console.error(error.data);
|
||||
else if (error.type === 'IOError')
|
||||
console.error(error.data.data);
|
||||
else if (error.type === 'DaoError')
|
||||
console.error(error.data);
|
||||
|
||||
console.log(error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
|||
21
apps/oneclient/frontend/src/routes/test/app.tsx
Normal file
21
apps/oneclient/frontend/src/routes/test/app.tsx
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import useMyContext from '@/components/MyContext';
|
||||
import { createFileRoute } from '@tanstack/react-router';
|
||||
|
||||
export const Route = createFileRoute('/test/app')({
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
const myContext = useMyContext();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div>Hello "/test/app"!</div>
|
||||
<div>
|
||||
Value from MyContext:
|
||||
{' '}
|
||||
{myContext.text}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
15
apps/oneclient/frontend/src/routes/test/route.tsx
Normal file
15
apps/oneclient/frontend/src/routes/test/route.tsx
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import { MyContextProvider } from '@/components/MyContext';
|
||||
import { createFileRoute, Outlet } from '@tanstack/react-router';
|
||||
|
||||
export const Route = createFileRoute('/test')({
|
||||
component: RouteComponent,
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
return (
|
||||
<MyContextProvider value={{ text: 'Hello from cool!' }}>
|
||||
<div>Hello "/test"!</div>
|
||||
<Outlet />
|
||||
</MyContextProvider>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
// This file has been generated by Specta. DO NOT EDIT.
|
||||
|
||||
import { createTauRPCProxy as createProxy, type InferCommandOutput } from 'taurpc'
|
||||
type TAURI_CHANNEL<T> = (response: T) => void
|
||||
|
||||
|
||||
export type ClusterError = { InvalidVersion: string } | "MissingJavaVersion" | "ClusterDownloading" | "ClusterAlreadyRunning"
|
||||
|
||||
export type ClusterStage = "notready" | "downloading" | "repairing" | "ready"
|
||||
|
||||
export type CreateCluster = { name: string; mc_version: string; mc_loader: GameLoader; mc_loader_version: string | null; icon: Icon | null }
|
||||
|
||||
export type CryptoError = { InvalidHash: { algorithm: HashAlgorithm; expected: string; actual: string } } | "InvalidAlgorithm"
|
||||
|
||||
export type DaoError = "NotFound" | "AlreadyExists" | { InvalidValue: [string, string] }
|
||||
|
||||
export type DirectoryError = "BaseDir"
|
||||
|
||||
export type DiscordError = "MissingClientId" | "ConnectError"
|
||||
|
||||
export type GameLoader = "vanilla" | "forge" | "neoforge" | "quilt" | "fabric" | "legacyfabric"
|
||||
|
||||
export type HashAlgorithm = "Sha1" | "Sha256" | "Md5"
|
||||
|
||||
/**
|
||||
* A wrapper around generic and unhelpful [`std::io::Error`] messages.
|
||||
*/
|
||||
export type IOError = { InvalidAbsolutePath: string } | { IOErrorWrapper: { path: string } } | "IOError" | "DeserializeError" | "AsyncZipError"
|
||||
|
||||
export type Icon = string
|
||||
|
||||
export type IncompatiblePackageType = "McVersion" | "Loader"
|
||||
|
||||
export type IngressError = "NotFound"
|
||||
|
||||
export type IngressPayload = { id: string; message: string; ingress_type: IngressType; percent: number | null; total: number }
|
||||
|
||||
export type IngressType = { Download: { file_name: string } } | "JavaPrepare" | "JavaCheck" | "JavaLocate" | "MinecraftDownload" | { PrepareCluster: { cluster_name: string } }
|
||||
|
||||
export type JavaError = { ParseVersion: [string] } | "Execute" | "MissingJava"
|
||||
|
||||
export type LauncherError = { type: "DirError"; data: DirectoryError } | { type: "IOError"; data: IOError } | { type: "IngressError"; data: IngressError } | { type: "JavaError"; data: JavaError } | { type: "CryptoError"; data: CryptoError } | { type: "DiscordError"; data: DiscordError } | { type: "MetadataError"; data: MetadataError } | { type: "ClusterError"; data: ClusterError } | { type: "MinecraftAuthError"; data: MinecraftAuthError } | { type: "ProcessError"; data: ProcessError } | { type: "PackageError"; data: PackageError } | { type: "DaoError"; data: DaoError } | { type: "SerdeError" } | { type: "AnyhowError" } | { type: "DbError" } | { type: "ReqwestError" } | { type: "InterpulseError" } | { type: "RegexError" } | { type: "SemaphoreError" } | { type: "UrlError" } | { type: "TauriError" }
|
||||
|
||||
export type MessageLevel = "Info" | "Warn" | "Error"
|
||||
|
||||
export type MessagePayload = { level: MessageLevel; message: string }
|
||||
|
||||
export type MetadataError = "FetchError" | { NotModdedManifest: GameLoader } | { NotVanillaManifest: GameLoader } | "ParseError" | "NoMatchingLoader" | "NoMatchingVersion"
|
||||
|
||||
/**
|
||||
* Wrapper around all `Error`s that can occur during the Microsoft authentication process.
|
||||
*/
|
||||
export type MinecraftAuthError = "PublicKeyReading" | "PKCS8Error" | { SerializeError: { step: MinecraftAuthStep } } | { DeserializeError: { step: MinecraftAuthStep; raw: string } } | { RequestError: { step: MinecraftAuthStep } } | { SigningError: { step: MinecraftAuthStep } } | "HashError" | "SessionIdError"
|
||||
|
||||
/**
|
||||
* An ordered list of all MSA authentication steps.
|
||||
*/
|
||||
export type MinecraftAuthStep = "DeviceToken" | "SisuAuthenicate" | "OAuthToken" | "RefreshOAuthToken" | "SisuAuthorize" | "XstsAuthorize" | "MinecraftToken" | "MinecraftEntitlements" | "MinecraftProfile"
|
||||
|
||||
/**
|
||||
* A structure of all needed Minecraft credentials for logging in and account management.
|
||||
*/
|
||||
export type MinecraftCredentials = {
|
||||
/**
|
||||
* The uuid of the credentials.
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* The username of the Minecraft account.
|
||||
*/
|
||||
username: string;
|
||||
/**
|
||||
* The access token as a String.
|
||||
*/
|
||||
access_token: string;
|
||||
/**
|
||||
* The refresh token as a string for [`MinecraftState#refresh`].
|
||||
*/
|
||||
refresh_token: string;
|
||||
/**
|
||||
* The time that the access token expires as a [`DateTime<Utc>`].
|
||||
*/
|
||||
expires: string }
|
||||
|
||||
export type Model = { id: bigint; folder_name: string; stage: ClusterStage; created_at: string; group_id: bigint | null; name: string; mc_version: string; mc_loader: GameLoader; mc_loader_version: string | null; last_played: string | null; overall_played: bigint | null; icon_url: Icon | null; setting_profile_name: string | null; linked_pack_id: string | null; linked_pack_version: string | null }
|
||||
|
||||
export type PackageError = "NoPrimaryFile" | "IsModPack" | { Incompatible: IncompatiblePackageType }
|
||||
|
||||
export type Process = { pid: number; started_at: string; cluster_id: bigint; post_hook: string | null; account_id: string }
|
||||
|
||||
export type ProcessError = { HookUnsuccessful: number } | "NoPid"
|
||||
|
||||
export type ProcessPayload = { type: "Starting"; command: string } | { type: "Started"; process: Process } | { type: "Stopped"; pid: number; exit_code: number } | { type: "Output"; pid: number; output: string }
|
||||
|
||||
export type Resolution = { width: number; height: number }
|
||||
|
||||
export type SettingProfileModel = { name: string; java_id: bigint | null; res: Resolution | null; force_fullscreen: boolean | null; mem_max: number | null; launch_args: string | null; launch_env: string | null; hook_pre: string | null; hook_wrapper: string | null; hook_post: string | null; os_extra: SettingsOsExtra | null }
|
||||
|
||||
export type SettingsOsExtra = Record<string, never>
|
||||
|
||||
const ARGS_MAP = { 'events':'{"process":["event"],"message":["event"],"ingress":["event"]}', 'onelauncher':'{"return_error":[],"open_dev_tools":[]}', 'core':'{"getProfileOrDefault":["name"],"setDefaultUser":["uuid"],"launchCluster":["id","uuid"],"getClusterById":["id"],"removeCluster":["id"],"createCluster":["options"],"getUsers":[],"getUser":["uuid"],"getGlobalProfile":[],"getDefaultUser":["fallback"],"getClusters":[],"removeUser":["uuid"],"openMsaLogin":[]}' }
|
||||
export type Router = { 'onelauncher': { return_error: () => Promise<null>,
|
||||
open_dev_tools: () => Promise<void> },
|
||||
'core': { getClusters: () => Promise<Model[]>,
|
||||
getClusterById: (id: bigint) => Promise<Model | null>,
|
||||
removeCluster: (id: bigint) => Promise<null>,
|
||||
createCluster: (options: CreateCluster) => Promise<Model>,
|
||||
launchCluster: (id: bigint, uuid: string | null) => Promise<null>,
|
||||
getProfileOrDefault: (name: string | null) => Promise<SettingProfileModel>,
|
||||
getGlobalProfile: () => Promise<SettingProfileModel>,
|
||||
getUsers: () => Promise<MinecraftCredentials[]>,
|
||||
getUser: (uuid: string) => Promise<MinecraftCredentials | null>,
|
||||
removeUser: (uuid: string) => Promise<null>,
|
||||
getDefaultUser: (fallback: boolean | null) => Promise<MinecraftCredentials | null>,
|
||||
setDefaultUser: (uuid: string | null) => Promise<null>,
|
||||
openMsaLogin: () => Promise<MinecraftCredentials | null> },
|
||||
'events': { ingress: (event: IngressPayload) => Promise<void>,
|
||||
message: (event: MessagePayload) => Promise<void>,
|
||||
process: (event: ProcessPayload) => Promise<void> } };
|
||||
|
||||
|
||||
export type { InferCommandOutput }
|
||||
export const createTauRPCProxy = () => createProxy<Router>(ARGS_MAP)
|
||||
|
|
@ -1,669 +0,0 @@
|
|||
/* eslint-disable */
|
||||
|
||||
// @ts-nocheck
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
|
||||
// This file was automatically generated by TanStack Router.
|
||||
// You should NOT make any changes in this file as it will be overwritten.
|
||||
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
|
||||
|
||||
// Import Routes
|
||||
|
||||
import { Route as rootRoute } from './routes/__root'
|
||||
import { Route as OnboardingRouteImport } from './routes/onboarding/route'
|
||||
import { Route as AppRouteImport } from './routes/app/route'
|
||||
import { Route as IndexImport } from './routes/index'
|
||||
import { Route as OnboardingIndexImport } from './routes/onboarding/index'
|
||||
import { Route as AppIndexImport } from './routes/app/index'
|
||||
import { Route as OnboardingSummaryImport } from './routes/onboarding/summary'
|
||||
import { Route as OnboardingLoginImport } from './routes/onboarding/login'
|
||||
import { Route as OnboardingLanguageImport } from './routes/onboarding/language'
|
||||
import { Route as OnboardingImportImport } from './routes/onboarding/import'
|
||||
import { Route as OnboardingCompleteImport } from './routes/onboarding/complete'
|
||||
import { Route as AppSettingsRouteImport } from './routes/app/settings/route'
|
||||
import { Route as AppClusterRouteImport } from './routes/app/cluster/route'
|
||||
import { Route as AppSettingsIndexImport } from './routes/app/settings/index'
|
||||
import { Route as AppClusterIndexImport } from './routes/app/cluster/index'
|
||||
import { Route as AppBrowserIndexImport } from './routes/app/browser/index'
|
||||
import { Route as AppSettingsMinecraftImport } from './routes/app/settings/minecraft'
|
||||
import { Route as AppSettingsAppearanceImport } from './routes/app/settings/appearance'
|
||||
import { Route as AppSettingsAccountsImport } from './routes/app/settings/accounts'
|
||||
import { Route as AppClusterWorldsImport } from './routes/app/cluster/worlds'
|
||||
import { Route as AppClusterSettingsImport } from './routes/app/cluster/settings'
|
||||
import { Route as AppClusterScreenshotsImport } from './routes/app/cluster/screenshots'
|
||||
|
||||
// Create/Update Routes
|
||||
|
||||
const OnboardingRouteRoute = OnboardingRouteImport.update({
|
||||
id: '/onboarding',
|
||||
path: '/onboarding',
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any)
|
||||
|
||||
const AppRouteRoute = AppRouteImport.update({
|
||||
id: '/app',
|
||||
path: '/app',
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any)
|
||||
|
||||
const IndexRoute = IndexImport.update({
|
||||
id: '/',
|
||||
path: '/',
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any)
|
||||
|
||||
const OnboardingIndexRoute = OnboardingIndexImport.update({
|
||||
id: '/',
|
||||
path: '/',
|
||||
getParentRoute: () => OnboardingRouteRoute,
|
||||
} as any)
|
||||
|
||||
const AppIndexRoute = AppIndexImport.update({
|
||||
id: '/',
|
||||
path: '/',
|
||||
getParentRoute: () => AppRouteRoute,
|
||||
} as any)
|
||||
|
||||
const OnboardingSummaryRoute = OnboardingSummaryImport.update({
|
||||
id: '/summary',
|
||||
path: '/summary',
|
||||
getParentRoute: () => OnboardingRouteRoute,
|
||||
} as any)
|
||||
|
||||
const OnboardingLoginRoute = OnboardingLoginImport.update({
|
||||
id: '/login',
|
||||
path: '/login',
|
||||
getParentRoute: () => OnboardingRouteRoute,
|
||||
} as any)
|
||||
|
||||
const OnboardingLanguageRoute = OnboardingLanguageImport.update({
|
||||
id: '/language',
|
||||
path: '/language',
|
||||
getParentRoute: () => OnboardingRouteRoute,
|
||||
} as any)
|
||||
|
||||
const OnboardingImportRoute = OnboardingImportImport.update({
|
||||
id: '/import',
|
||||
path: '/import',
|
||||
getParentRoute: () => OnboardingRouteRoute,
|
||||
} as any)
|
||||
|
||||
const OnboardingCompleteRoute = OnboardingCompleteImport.update({
|
||||
id: '/complete',
|
||||
path: '/complete',
|
||||
getParentRoute: () => OnboardingRouteRoute,
|
||||
} as any)
|
||||
|
||||
const AppSettingsRouteRoute = AppSettingsRouteImport.update({
|
||||
id: '/settings',
|
||||
path: '/settings',
|
||||
getParentRoute: () => AppRouteRoute,
|
||||
} as any)
|
||||
|
||||
const AppClusterRouteRoute = AppClusterRouteImport.update({
|
||||
id: '/cluster',
|
||||
path: '/cluster',
|
||||
getParentRoute: () => AppRouteRoute,
|
||||
} as any)
|
||||
|
||||
const AppSettingsIndexRoute = AppSettingsIndexImport.update({
|
||||
id: '/',
|
||||
path: '/',
|
||||
getParentRoute: () => AppSettingsRouteRoute,
|
||||
} as any)
|
||||
|
||||
const AppClusterIndexRoute = AppClusterIndexImport.update({
|
||||
id: '/',
|
||||
path: '/',
|
||||
getParentRoute: () => AppClusterRouteRoute,
|
||||
} as any)
|
||||
|
||||
const AppBrowserIndexRoute = AppBrowserIndexImport.update({
|
||||
id: '/browser/',
|
||||
path: '/browser/',
|
||||
getParentRoute: () => AppRouteRoute,
|
||||
} as any)
|
||||
|
||||
const AppSettingsMinecraftRoute = AppSettingsMinecraftImport.update({
|
||||
id: '/minecraft',
|
||||
path: '/minecraft',
|
||||
getParentRoute: () => AppSettingsRouteRoute,
|
||||
} as any)
|
||||
|
||||
const AppSettingsAppearanceRoute = AppSettingsAppearanceImport.update({
|
||||
id: '/appearance',
|
||||
path: '/appearance',
|
||||
getParentRoute: () => AppSettingsRouteRoute,
|
||||
} as any)
|
||||
|
||||
const AppSettingsAccountsRoute = AppSettingsAccountsImport.update({
|
||||
id: '/accounts',
|
||||
path: '/accounts',
|
||||
getParentRoute: () => AppSettingsRouteRoute,
|
||||
} as any)
|
||||
|
||||
const AppClusterWorldsRoute = AppClusterWorldsImport.update({
|
||||
id: '/worlds',
|
||||
path: '/worlds',
|
||||
getParentRoute: () => AppClusterRouteRoute,
|
||||
} as any)
|
||||
|
||||
const AppClusterSettingsRoute = AppClusterSettingsImport.update({
|
||||
id: '/settings',
|
||||
path: '/settings',
|
||||
getParentRoute: () => AppClusterRouteRoute,
|
||||
} as any)
|
||||
|
||||
const AppClusterScreenshotsRoute = AppClusterScreenshotsImport.update({
|
||||
id: '/screenshots',
|
||||
path: '/screenshots',
|
||||
getParentRoute: () => AppClusterRouteRoute,
|
||||
} as any)
|
||||
|
||||
// Populate the FileRoutesByPath interface
|
||||
|
||||
declare module '@tanstack/react-router' {
|
||||
interface FileRoutesByPath {
|
||||
'/': {
|
||||
id: '/'
|
||||
path: '/'
|
||||
fullPath: '/'
|
||||
preLoaderRoute: typeof IndexImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
'/app': {
|
||||
id: '/app'
|
||||
path: '/app'
|
||||
fullPath: '/app'
|
||||
preLoaderRoute: typeof AppRouteImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
'/onboarding': {
|
||||
id: '/onboarding'
|
||||
path: '/onboarding'
|
||||
fullPath: '/onboarding'
|
||||
preLoaderRoute: typeof OnboardingRouteImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
'/app/cluster': {
|
||||
id: '/app/cluster'
|
||||
path: '/cluster'
|
||||
fullPath: '/app/cluster'
|
||||
preLoaderRoute: typeof AppClusterRouteImport
|
||||
parentRoute: typeof AppRouteImport
|
||||
}
|
||||
'/app/settings': {
|
||||
id: '/app/settings'
|
||||
path: '/settings'
|
||||
fullPath: '/app/settings'
|
||||
preLoaderRoute: typeof AppSettingsRouteImport
|
||||
parentRoute: typeof AppRouteImport
|
||||
}
|
||||
'/onboarding/complete': {
|
||||
id: '/onboarding/complete'
|
||||
path: '/complete'
|
||||
fullPath: '/onboarding/complete'
|
||||
preLoaderRoute: typeof OnboardingCompleteImport
|
||||
parentRoute: typeof OnboardingRouteImport
|
||||
}
|
||||
'/onboarding/import': {
|
||||
id: '/onboarding/import'
|
||||
path: '/import'
|
||||
fullPath: '/onboarding/import'
|
||||
preLoaderRoute: typeof OnboardingImportImport
|
||||
parentRoute: typeof OnboardingRouteImport
|
||||
}
|
||||
'/onboarding/language': {
|
||||
id: '/onboarding/language'
|
||||
path: '/language'
|
||||
fullPath: '/onboarding/language'
|
||||
preLoaderRoute: typeof OnboardingLanguageImport
|
||||
parentRoute: typeof OnboardingRouteImport
|
||||
}
|
||||
'/onboarding/login': {
|
||||
id: '/onboarding/login'
|
||||
path: '/login'
|
||||
fullPath: '/onboarding/login'
|
||||
preLoaderRoute: typeof OnboardingLoginImport
|
||||
parentRoute: typeof OnboardingRouteImport
|
||||
}
|
||||
'/onboarding/summary': {
|
||||
id: '/onboarding/summary'
|
||||
path: '/summary'
|
||||
fullPath: '/onboarding/summary'
|
||||
preLoaderRoute: typeof OnboardingSummaryImport
|
||||
parentRoute: typeof OnboardingRouteImport
|
||||
}
|
||||
'/app/': {
|
||||
id: '/app/'
|
||||
path: '/'
|
||||
fullPath: '/app/'
|
||||
preLoaderRoute: typeof AppIndexImport
|
||||
parentRoute: typeof AppRouteImport
|
||||
}
|
||||
'/onboarding/': {
|
||||
id: '/onboarding/'
|
||||
path: '/'
|
||||
fullPath: '/onboarding/'
|
||||
preLoaderRoute: typeof OnboardingIndexImport
|
||||
parentRoute: typeof OnboardingRouteImport
|
||||
}
|
||||
'/app/cluster/screenshots': {
|
||||
id: '/app/cluster/screenshots'
|
||||
path: '/screenshots'
|
||||
fullPath: '/app/cluster/screenshots'
|
||||
preLoaderRoute: typeof AppClusterScreenshotsImport
|
||||
parentRoute: typeof AppClusterRouteImport
|
||||
}
|
||||
'/app/cluster/settings': {
|
||||
id: '/app/cluster/settings'
|
||||
path: '/settings'
|
||||
fullPath: '/app/cluster/settings'
|
||||
preLoaderRoute: typeof AppClusterSettingsImport
|
||||
parentRoute: typeof AppClusterRouteImport
|
||||
}
|
||||
'/app/cluster/worlds': {
|
||||
id: '/app/cluster/worlds'
|
||||
path: '/worlds'
|
||||
fullPath: '/app/cluster/worlds'
|
||||
preLoaderRoute: typeof AppClusterWorldsImport
|
||||
parentRoute: typeof AppClusterRouteImport
|
||||
}
|
||||
'/app/settings/accounts': {
|
||||
id: '/app/settings/accounts'
|
||||
path: '/accounts'
|
||||
fullPath: '/app/settings/accounts'
|
||||
preLoaderRoute: typeof AppSettingsAccountsImport
|
||||
parentRoute: typeof AppSettingsRouteImport
|
||||
}
|
||||
'/app/settings/appearance': {
|
||||
id: '/app/settings/appearance'
|
||||
path: '/appearance'
|
||||
fullPath: '/app/settings/appearance'
|
||||
preLoaderRoute: typeof AppSettingsAppearanceImport
|
||||
parentRoute: typeof AppSettingsRouteImport
|
||||
}
|
||||
'/app/settings/minecraft': {
|
||||
id: '/app/settings/minecraft'
|
||||
path: '/minecraft'
|
||||
fullPath: '/app/settings/minecraft'
|
||||
preLoaderRoute: typeof AppSettingsMinecraftImport
|
||||
parentRoute: typeof AppSettingsRouteImport
|
||||
}
|
||||
'/app/browser/': {
|
||||
id: '/app/browser/'
|
||||
path: '/browser'
|
||||
fullPath: '/app/browser'
|
||||
preLoaderRoute: typeof AppBrowserIndexImport
|
||||
parentRoute: typeof AppRouteImport
|
||||
}
|
||||
'/app/cluster/': {
|
||||
id: '/app/cluster/'
|
||||
path: '/'
|
||||
fullPath: '/app/cluster/'
|
||||
preLoaderRoute: typeof AppClusterIndexImport
|
||||
parentRoute: typeof AppClusterRouteImport
|
||||
}
|
||||
'/app/settings/': {
|
||||
id: '/app/settings/'
|
||||
path: '/'
|
||||
fullPath: '/app/settings/'
|
||||
preLoaderRoute: typeof AppSettingsIndexImport
|
||||
parentRoute: typeof AppSettingsRouteImport
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create and export the route tree
|
||||
|
||||
interface AppClusterRouteRouteChildren {
|
||||
AppClusterScreenshotsRoute: typeof AppClusterScreenshotsRoute
|
||||
AppClusterSettingsRoute: typeof AppClusterSettingsRoute
|
||||
AppClusterWorldsRoute: typeof AppClusterWorldsRoute
|
||||
AppClusterIndexRoute: typeof AppClusterIndexRoute
|
||||
}
|
||||
|
||||
const AppClusterRouteRouteChildren: AppClusterRouteRouteChildren = {
|
||||
AppClusterScreenshotsRoute: AppClusterScreenshotsRoute,
|
||||
AppClusterSettingsRoute: AppClusterSettingsRoute,
|
||||
AppClusterWorldsRoute: AppClusterWorldsRoute,
|
||||
AppClusterIndexRoute: AppClusterIndexRoute,
|
||||
}
|
||||
|
||||
const AppClusterRouteRouteWithChildren = AppClusterRouteRoute._addFileChildren(
|
||||
AppClusterRouteRouteChildren,
|
||||
)
|
||||
|
||||
interface AppSettingsRouteRouteChildren {
|
||||
AppSettingsAccountsRoute: typeof AppSettingsAccountsRoute
|
||||
AppSettingsAppearanceRoute: typeof AppSettingsAppearanceRoute
|
||||
AppSettingsMinecraftRoute: typeof AppSettingsMinecraftRoute
|
||||
AppSettingsIndexRoute: typeof AppSettingsIndexRoute
|
||||
}
|
||||
|
||||
const AppSettingsRouteRouteChildren: AppSettingsRouteRouteChildren = {
|
||||
AppSettingsAccountsRoute: AppSettingsAccountsRoute,
|
||||
AppSettingsAppearanceRoute: AppSettingsAppearanceRoute,
|
||||
AppSettingsMinecraftRoute: AppSettingsMinecraftRoute,
|
||||
AppSettingsIndexRoute: AppSettingsIndexRoute,
|
||||
}
|
||||
|
||||
const AppSettingsRouteRouteWithChildren =
|
||||
AppSettingsRouteRoute._addFileChildren(AppSettingsRouteRouteChildren)
|
||||
|
||||
interface AppRouteRouteChildren {
|
||||
AppClusterRouteRoute: typeof AppClusterRouteRouteWithChildren
|
||||
AppSettingsRouteRoute: typeof AppSettingsRouteRouteWithChildren
|
||||
AppIndexRoute: typeof AppIndexRoute
|
||||
AppBrowserIndexRoute: typeof AppBrowserIndexRoute
|
||||
}
|
||||
|
||||
const AppRouteRouteChildren: AppRouteRouteChildren = {
|
||||
AppClusterRouteRoute: AppClusterRouteRouteWithChildren,
|
||||
AppSettingsRouteRoute: AppSettingsRouteRouteWithChildren,
|
||||
AppIndexRoute: AppIndexRoute,
|
||||
AppBrowserIndexRoute: AppBrowserIndexRoute,
|
||||
}
|
||||
|
||||
const AppRouteRouteWithChildren = AppRouteRoute._addFileChildren(
|
||||
AppRouteRouteChildren,
|
||||
)
|
||||
|
||||
interface OnboardingRouteRouteChildren {
|
||||
OnboardingCompleteRoute: typeof OnboardingCompleteRoute
|
||||
OnboardingImportRoute: typeof OnboardingImportRoute
|
||||
OnboardingLanguageRoute: typeof OnboardingLanguageRoute
|
||||
OnboardingLoginRoute: typeof OnboardingLoginRoute
|
||||
OnboardingSummaryRoute: typeof OnboardingSummaryRoute
|
||||
OnboardingIndexRoute: typeof OnboardingIndexRoute
|
||||
}
|
||||
|
||||
const OnboardingRouteRouteChildren: OnboardingRouteRouteChildren = {
|
||||
OnboardingCompleteRoute: OnboardingCompleteRoute,
|
||||
OnboardingImportRoute: OnboardingImportRoute,
|
||||
OnboardingLanguageRoute: OnboardingLanguageRoute,
|
||||
OnboardingLoginRoute: OnboardingLoginRoute,
|
||||
OnboardingSummaryRoute: OnboardingSummaryRoute,
|
||||
OnboardingIndexRoute: OnboardingIndexRoute,
|
||||
}
|
||||
|
||||
const OnboardingRouteRouteWithChildren = OnboardingRouteRoute._addFileChildren(
|
||||
OnboardingRouteRouteChildren,
|
||||
)
|
||||
|
||||
export interface FileRoutesByFullPath {
|
||||
'/': typeof IndexRoute
|
||||
'/app': typeof AppRouteRouteWithChildren
|
||||
'/onboarding': typeof OnboardingRouteRouteWithChildren
|
||||
'/app/cluster': typeof AppClusterRouteRouteWithChildren
|
||||
'/app/settings': typeof AppSettingsRouteRouteWithChildren
|
||||
'/onboarding/complete': typeof OnboardingCompleteRoute
|
||||
'/onboarding/import': typeof OnboardingImportRoute
|
||||
'/onboarding/language': typeof OnboardingLanguageRoute
|
||||
'/onboarding/login': typeof OnboardingLoginRoute
|
||||
'/onboarding/summary': typeof OnboardingSummaryRoute
|
||||
'/app/': typeof AppIndexRoute
|
||||
'/onboarding/': typeof OnboardingIndexRoute
|
||||
'/app/cluster/screenshots': typeof AppClusterScreenshotsRoute
|
||||
'/app/cluster/settings': typeof AppClusterSettingsRoute
|
||||
'/app/cluster/worlds': typeof AppClusterWorldsRoute
|
||||
'/app/settings/accounts': typeof AppSettingsAccountsRoute
|
||||
'/app/settings/appearance': typeof AppSettingsAppearanceRoute
|
||||
'/app/settings/minecraft': typeof AppSettingsMinecraftRoute
|
||||
'/app/browser': typeof AppBrowserIndexRoute
|
||||
'/app/cluster/': typeof AppClusterIndexRoute
|
||||
'/app/settings/': typeof AppSettingsIndexRoute
|
||||
}
|
||||
|
||||
export interface FileRoutesByTo {
|
||||
'/': typeof IndexRoute
|
||||
'/onboarding/complete': typeof OnboardingCompleteRoute
|
||||
'/onboarding/import': typeof OnboardingImportRoute
|
||||
'/onboarding/language': typeof OnboardingLanguageRoute
|
||||
'/onboarding/login': typeof OnboardingLoginRoute
|
||||
'/onboarding/summary': typeof OnboardingSummaryRoute
|
||||
'/app': typeof AppIndexRoute
|
||||
'/onboarding': typeof OnboardingIndexRoute
|
||||
'/app/cluster/screenshots': typeof AppClusterScreenshotsRoute
|
||||
'/app/cluster/settings': typeof AppClusterSettingsRoute
|
||||
'/app/cluster/worlds': typeof AppClusterWorldsRoute
|
||||
'/app/settings/accounts': typeof AppSettingsAccountsRoute
|
||||
'/app/settings/appearance': typeof AppSettingsAppearanceRoute
|
||||
'/app/settings/minecraft': typeof AppSettingsMinecraftRoute
|
||||
'/app/browser': typeof AppBrowserIndexRoute
|
||||
'/app/cluster': typeof AppClusterIndexRoute
|
||||
'/app/settings': typeof AppSettingsIndexRoute
|
||||
}
|
||||
|
||||
export interface FileRoutesById {
|
||||
__root__: typeof rootRoute
|
||||
'/': typeof IndexRoute
|
||||
'/app': typeof AppRouteRouteWithChildren
|
||||
'/onboarding': typeof OnboardingRouteRouteWithChildren
|
||||
'/app/cluster': typeof AppClusterRouteRouteWithChildren
|
||||
'/app/settings': typeof AppSettingsRouteRouteWithChildren
|
||||
'/onboarding/complete': typeof OnboardingCompleteRoute
|
||||
'/onboarding/import': typeof OnboardingImportRoute
|
||||
'/onboarding/language': typeof OnboardingLanguageRoute
|
||||
'/onboarding/login': typeof OnboardingLoginRoute
|
||||
'/onboarding/summary': typeof OnboardingSummaryRoute
|
||||
'/app/': typeof AppIndexRoute
|
||||
'/onboarding/': typeof OnboardingIndexRoute
|
||||
'/app/cluster/screenshots': typeof AppClusterScreenshotsRoute
|
||||
'/app/cluster/settings': typeof AppClusterSettingsRoute
|
||||
'/app/cluster/worlds': typeof AppClusterWorldsRoute
|
||||
'/app/settings/accounts': typeof AppSettingsAccountsRoute
|
||||
'/app/settings/appearance': typeof AppSettingsAppearanceRoute
|
||||
'/app/settings/minecraft': typeof AppSettingsMinecraftRoute
|
||||
'/app/browser/': typeof AppBrowserIndexRoute
|
||||
'/app/cluster/': typeof AppClusterIndexRoute
|
||||
'/app/settings/': typeof AppSettingsIndexRoute
|
||||
}
|
||||
|
||||
export interface FileRouteTypes {
|
||||
fileRoutesByFullPath: FileRoutesByFullPath
|
||||
fullPaths:
|
||||
| '/'
|
||||
| '/app'
|
||||
| '/onboarding'
|
||||
| '/app/cluster'
|
||||
| '/app/settings'
|
||||
| '/onboarding/complete'
|
||||
| '/onboarding/import'
|
||||
| '/onboarding/language'
|
||||
| '/onboarding/login'
|
||||
| '/onboarding/summary'
|
||||
| '/app/'
|
||||
| '/onboarding/'
|
||||
| '/app/cluster/screenshots'
|
||||
| '/app/cluster/settings'
|
||||
| '/app/cluster/worlds'
|
||||
| '/app/settings/accounts'
|
||||
| '/app/settings/appearance'
|
||||
| '/app/settings/minecraft'
|
||||
| '/app/browser'
|
||||
| '/app/cluster/'
|
||||
| '/app/settings/'
|
||||
fileRoutesByTo: FileRoutesByTo
|
||||
to:
|
||||
| '/'
|
||||
| '/onboarding/complete'
|
||||
| '/onboarding/import'
|
||||
| '/onboarding/language'
|
||||
| '/onboarding/login'
|
||||
| '/onboarding/summary'
|
||||
| '/app'
|
||||
| '/onboarding'
|
||||
| '/app/cluster/screenshots'
|
||||
| '/app/cluster/settings'
|
||||
| '/app/cluster/worlds'
|
||||
| '/app/settings/accounts'
|
||||
| '/app/settings/appearance'
|
||||
| '/app/settings/minecraft'
|
||||
| '/app/browser'
|
||||
| '/app/cluster'
|
||||
| '/app/settings'
|
||||
id:
|
||||
| '__root__'
|
||||
| '/'
|
||||
| '/app'
|
||||
| '/onboarding'
|
||||
| '/app/cluster'
|
||||
| '/app/settings'
|
||||
| '/onboarding/complete'
|
||||
| '/onboarding/import'
|
||||
| '/onboarding/language'
|
||||
| '/onboarding/login'
|
||||
| '/onboarding/summary'
|
||||
| '/app/'
|
||||
| '/onboarding/'
|
||||
| '/app/cluster/screenshots'
|
||||
| '/app/cluster/settings'
|
||||
| '/app/cluster/worlds'
|
||||
| '/app/settings/accounts'
|
||||
| '/app/settings/appearance'
|
||||
| '/app/settings/minecraft'
|
||||
| '/app/browser/'
|
||||
| '/app/cluster/'
|
||||
| '/app/settings/'
|
||||
fileRoutesById: FileRoutesById
|
||||
}
|
||||
|
||||
export interface RootRouteChildren {
|
||||
IndexRoute: typeof IndexRoute
|
||||
AppRouteRoute: typeof AppRouteRouteWithChildren
|
||||
OnboardingRouteRoute: typeof OnboardingRouteRouteWithChildren
|
||||
}
|
||||
|
||||
const rootRouteChildren: RootRouteChildren = {
|
||||
IndexRoute: IndexRoute,
|
||||
AppRouteRoute: AppRouteRouteWithChildren,
|
||||
OnboardingRouteRoute: OnboardingRouteRouteWithChildren,
|
||||
}
|
||||
|
||||
export const routeTree = rootRoute
|
||||
._addFileChildren(rootRouteChildren)
|
||||
._addFileTypes<FileRouteTypes>()
|
||||
|
||||
/* ROUTE_MANIFEST_START
|
||||
{
|
||||
"routes": {
|
||||
"__root__": {
|
||||
"filePath": "__root.tsx",
|
||||
"children": [
|
||||
"/",
|
||||
"/app",
|
||||
"/onboarding"
|
||||
]
|
||||
},
|
||||
"/": {
|
||||
"filePath": "index.tsx"
|
||||
},
|
||||
"/app": {
|
||||
"filePath": "app/route.tsx",
|
||||
"children": [
|
||||
"/app/cluster",
|
||||
"/app/settings",
|
||||
"/app/",
|
||||
"/app/browser/"
|
||||
]
|
||||
},
|
||||
"/onboarding": {
|
||||
"filePath": "onboarding/route.tsx",
|
||||
"children": [
|
||||
"/onboarding/complete",
|
||||
"/onboarding/import",
|
||||
"/onboarding/language",
|
||||
"/onboarding/login",
|
||||
"/onboarding/summary",
|
||||
"/onboarding/"
|
||||
]
|
||||
},
|
||||
"/app/cluster": {
|
||||
"filePath": "app/cluster/route.tsx",
|
||||
"parent": "/app",
|
||||
"children": [
|
||||
"/app/cluster/screenshots",
|
||||
"/app/cluster/settings",
|
||||
"/app/cluster/worlds",
|
||||
"/app/cluster/"
|
||||
]
|
||||
},
|
||||
"/app/settings": {
|
||||
"filePath": "app/settings/route.tsx",
|
||||
"parent": "/app",
|
||||
"children": [
|
||||
"/app/settings/accounts",
|
||||
"/app/settings/appearance",
|
||||
"/app/settings/minecraft",
|
||||
"/app/settings/"
|
||||
]
|
||||
},
|
||||
"/onboarding/complete": {
|
||||
"filePath": "onboarding/complete.tsx",
|
||||
"parent": "/onboarding"
|
||||
},
|
||||
"/onboarding/import": {
|
||||
"filePath": "onboarding/import.tsx",
|
||||
"parent": "/onboarding"
|
||||
},
|
||||
"/onboarding/language": {
|
||||
"filePath": "onboarding/language.tsx",
|
||||
"parent": "/onboarding"
|
||||
},
|
||||
"/onboarding/login": {
|
||||
"filePath": "onboarding/login.tsx",
|
||||
"parent": "/onboarding"
|
||||
},
|
||||
"/onboarding/summary": {
|
||||
"filePath": "onboarding/summary.tsx",
|
||||
"parent": "/onboarding"
|
||||
},
|
||||
"/app/": {
|
||||
"filePath": "app/index.tsx",
|
||||
"parent": "/app"
|
||||
},
|
||||
"/onboarding/": {
|
||||
"filePath": "onboarding/index.tsx",
|
||||
"parent": "/onboarding"
|
||||
},
|
||||
"/app/cluster/screenshots": {
|
||||
"filePath": "app/cluster/screenshots.tsx",
|
||||
"parent": "/app/cluster"
|
||||
},
|
||||
"/app/cluster/settings": {
|
||||
"filePath": "app/cluster/settings.tsx",
|
||||
"parent": "/app/cluster"
|
||||
},
|
||||
"/app/cluster/worlds": {
|
||||
"filePath": "app/cluster/worlds.tsx",
|
||||
"parent": "/app/cluster"
|
||||
},
|
||||
"/app/settings/accounts": {
|
||||
"filePath": "app/settings/accounts.tsx",
|
||||
"parent": "/app/settings"
|
||||
},
|
||||
"/app/settings/appearance": {
|
||||
"filePath": "app/settings/appearance.tsx",
|
||||
"parent": "/app/settings"
|
||||
},
|
||||
"/app/settings/minecraft": {
|
||||
"filePath": "app/settings/minecraft.tsx",
|
||||
"parent": "/app/settings"
|
||||
},
|
||||
"/app/browser/": {
|
||||
"filePath": "app/browser/index.tsx",
|
||||
"parent": "/app"
|
||||
},
|
||||
"/app/cluster/": {
|
||||
"filePath": "app/cluster/index.tsx",
|
||||
"parent": "/app/cluster"
|
||||
},
|
||||
"/app/settings/": {
|
||||
"filePath": "app/settings/index.tsx",
|
||||
"parent": "/app/settings"
|
||||
}
|
||||
}
|
||||
}
|
||||
ROUTE_MANIFEST_END */
|
||||
|
|
@ -10,11 +10,11 @@ async fn main() -> LauncherResult<()> {
|
|||
|
||||
println!("Initialized: {}", metadata.initialized());
|
||||
println!("Minecraft: {:?}", metadata.get_vanilla_or_fetch().await.is_ok());
|
||||
println!("Forge: {:?}", metadata.get_modded_or_fetch(GameLoader::Forge).await.is_ok());
|
||||
println!("Forge: {:?}", metadata.get_modded_or_fetch(&GameLoader::Forge).await.is_ok());
|
||||
println!("Initialized: {}", metadata.initialized());
|
||||
println!("NeoForge: {:?}", metadata.get_modded_or_fetch(GameLoader::NeoForge).await.is_ok());
|
||||
println!("Fabric: {:?}", metadata.get_modded_or_fetch(GameLoader::Fabric).await.is_ok());
|
||||
println!("Quilt: {:?}", metadata.get_modded_or_fetch(GameLoader::Quilt).await.is_ok());
|
||||
println!("NeoForge: {:?}", metadata.get_modded_or_fetch(&GameLoader::NeoForge).await.is_ok());
|
||||
println!("Fabric: {:?}", metadata.get_modded_or_fetch(&GameLoader::Fabric).await.is_ok());
|
||||
println!("Quilt: {:?}", metadata.get_modded_or_fetch(&GameLoader::Quilt).await.is_ok());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -6,7 +6,6 @@ use onelauncher_entity::{clusters, java_versions};
|
|||
use onelauncher_entity::icon::Icon;
|
||||
use onelauncher_entity::loader::GameLoader;
|
||||
use sea_orm::ActiveValue::Set;
|
||||
use serde::Serialize;
|
||||
use tokio::process::Command;
|
||||
|
||||
use crate::api::game::arguments;
|
||||
|
|
@ -25,8 +24,8 @@ pub use sync::*;
|
|||
|
||||
use super::ingress::init_ingress;
|
||||
|
||||
#[onelauncher_macro::specta]
|
||||
#[derive(Debug, thiserror::Error, Serialize)]
|
||||
#[onelauncher_macro::error]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum ClusterError {
|
||||
#[error("version '{0}' was not found")]
|
||||
InvalidVersion(String),
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ pub async fn launch_minecraft(
|
|||
arguments::java_arguments(
|
||||
args.get(&interpulse::api::minecraft::ArgumentType::Jvm)
|
||||
.map(Vec::as_slice),
|
||||
&dirs.natives_dir().join(&version_name),
|
||||
&dirs.natives_dir().join(&version.id),
|
||||
&dirs.libraries_dir(),
|
||||
&arguments::classpaths(
|
||||
&dirs.libraries_dir(),
|
||||
|
|
|
|||
|
|
@ -386,7 +386,7 @@ pub async fn download_libraries(
|
|||
Ok(failed)
|
||||
}
|
||||
|
||||
// MARK: Loader Version
|
||||
// MARK: Get Loader
|
||||
/// Gets the loader version for a given Minecraft version and loader
|
||||
/// If `loader_version` is `None`, it will return the latest stable version else
|
||||
/// it will return the specified version if found
|
||||
|
|
@ -402,7 +402,7 @@ pub async fn get_loader_version(
|
|||
|
||||
let state = State::get().await?;
|
||||
let metadata = state.metadata.read().await;
|
||||
let manifest = metadata.get_modded(loader)?;
|
||||
let manifest = metadata.get_modded(&loader)?;
|
||||
|
||||
let Some(loaders) = manifest.game_versions.iter().find(|it| {
|
||||
it.id
|
||||
|
|
@ -422,3 +422,23 @@ pub async fn get_loader_version(
|
|||
|
||||
Ok(Some(loader_version))
|
||||
}
|
||||
|
||||
// MARK: Get Versions
|
||||
/// Gets the list of Minecraft versions from the metadata store
|
||||
#[tracing::instrument]
|
||||
pub async fn get_game_versions() -> LauncherResult<Vec<Version>> {
|
||||
let state = State::get().await?;
|
||||
let metadata = state.metadata.read().await;
|
||||
|
||||
let manifest = metadata.get_vanilla()?;
|
||||
Ok(manifest.versions.clone())
|
||||
}
|
||||
|
||||
/// Gets the list of modded loaders and their versions from the metadata store
|
||||
#[tracing::instrument]
|
||||
pub async fn get_loaders_for_version(mc_version: &str) -> LauncherResult<Vec<GameLoader>> {
|
||||
let state = State::get().await?;
|
||||
let mut metadata = state.metadata.write().await;
|
||||
|
||||
Ok(metadata.get_loaders_for_version(mc_version).await?)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,13 +12,13 @@ use crate::utils::io;
|
|||
|
||||
pub mod dao;
|
||||
|
||||
#[onelauncher_macro::specta]
|
||||
#[derive(Debug, thiserror::Error, Serialize)]
|
||||
#[onelauncher_macro::error]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum JavaError {
|
||||
#[error("failed to parse version '{0}'")]
|
||||
ParseVersion(String, #[source] #[serde(skip)] std::num::ParseIntError),
|
||||
ParseVersion(String, #[source] #[skip] std::num::ParseIntError),
|
||||
#[error("failed to execute java command")]
|
||||
Execute(#[from] #[serde(skip)] std::io::Error),
|
||||
Execute(#[from] #[skip] std::io::Error),
|
||||
#[error("no java installations found")]
|
||||
MissingJava,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ use onelauncher_entity::icon::Icon;
|
|||
use onelauncher_entity::package::PackageType;
|
||||
use onelauncher_entity::{clusters, packages};
|
||||
use reqwest::Method;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::error::{LauncherError, LauncherResult};
|
||||
use crate::store::Dirs;
|
||||
|
|
@ -19,8 +18,8 @@ pub mod provider;
|
|||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
#[onelauncher_macro::specta]
|
||||
#[derive(Debug, thiserror::Error, Serialize)]
|
||||
#[onelauncher_macro::error]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum PackageError {
|
||||
#[error("no file marked for download")]
|
||||
NoPrimaryFile,
|
||||
|
|
@ -30,8 +29,8 @@ pub enum PackageError {
|
|||
Incompatible(#[from] IncompatiblePackageType),
|
||||
}
|
||||
|
||||
#[onelauncher_macro::specta]
|
||||
#[derive(Debug, thiserror::Error, Serialize)]
|
||||
#[onelauncher_macro::error]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum IncompatiblePackageType {
|
||||
#[error("package is not compatible with the current version")]
|
||||
McVersion,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,13 @@ pub trait TauriLauncherApi {
|
|||
#[taurpc(alias = "getGlobalProfile")]
|
||||
async fn get_global_profile() -> SettingsProfile;
|
||||
|
||||
// Game Metadata
|
||||
#[taurpc(alias = "getGameVersions")]
|
||||
async fn get_game_versions() -> LauncherResult<Vec<Version>>;
|
||||
|
||||
#[taurpc(alias = "getLoadersForVersion")]
|
||||
async fn get_loaders_for_version(mc_version: String) -> LauncherResult<Vec<GameLoader>>;
|
||||
|
||||
|
||||
// Users
|
||||
#[taurpc(alias = "getUsers")]
|
||||
|
|
@ -69,6 +76,8 @@ pub struct TauriLauncherApiImpl;
|
|||
|
||||
#[taurpc::resolvers]
|
||||
impl TauriLauncherApi for TauriLauncherApiImpl {
|
||||
|
||||
// Clusters
|
||||
async fn get_clusters(self) -> LauncherResult<Vec<Cluster>> {
|
||||
api::cluster::dao::get_all_clusters().await
|
||||
}
|
||||
|
|
@ -84,13 +93,6 @@ impl TauriLauncherApi for TauriLauncherApiImpl {
|
|||
async fn create_cluster(self, options: CreateCluster) -> LauncherResult<Cluster> {
|
||||
let cluster = api::cluster::create_cluster(&options.name, &options.mc_version, options.mc_loader, options.mc_loader_version.as_deref(), options.icon).await?;
|
||||
|
||||
// if api::setting_profiles::dao::get_profile_by_name(&options.name).await?.is_none() {
|
||||
// api::setting_profiles::create_profile(&options.name, async |mut profile| {
|
||||
// profile.mem_max = sea_orm::ActiveValue::Set(Some(2048));
|
||||
// Ok(profile)
|
||||
// }).await?;
|
||||
// }
|
||||
|
||||
Ok(cluster)
|
||||
}
|
||||
|
||||
|
|
@ -113,14 +115,28 @@ impl TauriLauncherApi for TauriLauncherApiImpl {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_profile_or_default(self, name: Option<String>) -> LauncherResult<SettingsProfile> {
|
||||
api::setting_profiles::dao::get_profile_or_default(name.as_ref()).await
|
||||
}
|
||||
|
||||
// Setting Profiles
|
||||
async fn get_global_profile(self) -> SettingsProfile {
|
||||
api::setting_profiles::get_global_profile().await
|
||||
}
|
||||
|
||||
async fn get_profile_or_default(self, name: Option<String>) -> LauncherResult<SettingsProfile> {
|
||||
api::setting_profiles::dao::get_profile_or_default(name.as_ref()).await
|
||||
}
|
||||
|
||||
|
||||
// Game Metadata
|
||||
async fn get_loaders_for_version(self, mc_version: String) -> LauncherResult<Vec<GameLoader>> {
|
||||
api::game::metadata::get_loaders_for_version(&mc_version).await
|
||||
}
|
||||
|
||||
async fn get_game_versions(self) -> LauncherResult<Vec<Version>> {
|
||||
api::game::metadata::get_game_versions().await
|
||||
}
|
||||
|
||||
|
||||
// Users
|
||||
async fn get_users(self) -> LauncherResult<Vec<MinecraftCredentials>> {
|
||||
api::credentials::get_users().await
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
use serde::Serialize;
|
||||
|
||||
#[onelauncher_macro::specta]
|
||||
#[derive(thiserror::Error, Debug, Serialize)]
|
||||
#[serde(tag = "type", content = "data")]
|
||||
#[onelauncher_macro::error]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum LauncherError {
|
||||
#[error(transparent)]
|
||||
DirError(#[from] crate::store::DirectoryError),
|
||||
|
|
@ -30,41 +27,31 @@ pub enum LauncherError {
|
|||
DaoError(#[from] DaoError),
|
||||
|
||||
#[error("json error: {0}")]
|
||||
SerdeError(#[from] #[serde(skip)] serde_json::Error),
|
||||
SerdeError(#[from] #[skip] serde_json::Error),
|
||||
#[error(transparent)]
|
||||
AnyhowError(#[from] #[serde(skip)] anyhow::Error),
|
||||
AnyhowError(#[from] #[skip] anyhow::Error),
|
||||
#[error("database error: {0}")]
|
||||
DbError(#[from] #[serde(skip)] sea_orm::DbErr),
|
||||
DbError(#[from] #[skip] sea_orm::DbErr),
|
||||
#[error("http error: {0}")]
|
||||
ReqwestError(#[from] #[serde(skip)] reqwest::Error),
|
||||
ReqwestError(#[from] #[skip] reqwest::Error),
|
||||
#[error("meta error: {0}")]
|
||||
InterpulseError(#[from] #[serde(skip)] interpulse::Error),
|
||||
InterpulseError(#[from] #[skip] interpulse::Error),
|
||||
#[error(transparent)]
|
||||
RegexError(#[from] #[serde(skip)] regex::Error),
|
||||
RegexError(#[from] #[skip] regex::Error),
|
||||
#[error("couldn't acquire semaphore: {0}")]
|
||||
SemaphoreError(#[from] #[serde(skip)] tokio::sync::AcquireError),
|
||||
SemaphoreError(#[from] #[skip] tokio::sync::AcquireError),
|
||||
#[error(transparent)]
|
||||
UrlError(#[from] #[serde(skip)] url::ParseError),
|
||||
UrlError(#[from] #[skip] url::ParseError),
|
||||
|
||||
#[cfg(feature = "tauri")]
|
||||
#[error(transparent)]
|
||||
TauriError(#[from] #[serde(skip)] tauri::Error),
|
||||
TauriError(#[from] #[skip] tauri::Error),
|
||||
}
|
||||
|
||||
// impl serde::Serialize for LauncherError {
|
||||
// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
// where
|
||||
// S: serde::Serializer,
|
||||
// {
|
||||
// // Serialize the error as a string
|
||||
// serializer.serialize_str(&self.to_string())
|
||||
// }
|
||||
// }
|
||||
|
||||
pub type LauncherResult<T> = Result<T, LauncherError>;
|
||||
|
||||
#[onelauncher_macro::specta]
|
||||
#[derive(thiserror::Error, Debug, Serialize)]
|
||||
#[onelauncher_macro::error]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum DaoError {
|
||||
#[error("entity was not found")]
|
||||
NotFound,
|
||||
|
|
|
|||
|
|
@ -1010,19 +1010,23 @@ pub enum MinecraftAuthStep {
|
|||
}
|
||||
|
||||
/// Wrapper around all `Error`s that can occur during the Microsoft authentication process.
|
||||
#[onelauncher_macro::specta]
|
||||
#[derive(thiserror::Error, Debug, Serialize)]
|
||||
#[onelauncher_macro::error]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum MinecraftAuthError {
|
||||
#[error("failed to read public key during key generation")]
|
||||
PublicKeyReading,
|
||||
#[error("failed to serialize private key using PKCS8: {0}")]
|
||||
PKCS8Error(#[from] #[serde(skip)] p256::pkcs8::Error),
|
||||
PKCS8Error(
|
||||
#[from]
|
||||
#[skip]
|
||||
p256::pkcs8::Error
|
||||
),
|
||||
#[error("failed to serialize JSON during MSA step {step:?}: {source}")]
|
||||
SerializeError {
|
||||
step: MinecraftAuthStep,
|
||||
|
||||
#[source]
|
||||
#[serde(skip)]
|
||||
#[skip]
|
||||
source: serde_json::Error,
|
||||
},
|
||||
#[error(
|
||||
|
|
@ -1033,24 +1037,24 @@ pub enum MinecraftAuthError {
|
|||
raw: String,
|
||||
|
||||
#[source]
|
||||
#[serde(skip)]
|
||||
#[skip]
|
||||
source: serde_json::Error,
|
||||
|
||||
#[serde(skip)]
|
||||
#[skip]
|
||||
status_code: reqwest::StatusCode,
|
||||
},
|
||||
#[error("failed to request using HTTP during MSA step {step:?}: {source}")]
|
||||
RequestError {
|
||||
step: MinecraftAuthStep,
|
||||
#[source]
|
||||
#[serde(skip)]
|
||||
#[skip]
|
||||
source: reqwest::Error,
|
||||
},
|
||||
#[error("failed to create signed buffer during MSA step {step:?}: {source}")]
|
||||
SigningError {
|
||||
step: MinecraftAuthStep,
|
||||
#[source]
|
||||
#[serde(skip)]
|
||||
#[skip]
|
||||
source: std::io::Error,
|
||||
},
|
||||
#[error("failed to read user hash")]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use onelauncher_entity::package::{PackageType, Provider};
|
||||
use serde::Serialize;
|
||||
use tokio::sync::OnceCell;
|
||||
|
||||
use crate::{utils, LauncherResult};
|
||||
|
|
@ -16,8 +15,8 @@ pub struct Dirs {
|
|||
base_dir: PathBuf,
|
||||
}
|
||||
|
||||
#[onelauncher_macro::specta]
|
||||
#[derive(Debug, thiserror::Error, Serialize)]
|
||||
#[onelauncher_macro::error]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum DirectoryError {
|
||||
#[error("Failed to get the base directory for the launcher.")]
|
||||
BaseDir,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use std::sync::{atomic::AtomicBool, Arc};
|
||||
|
||||
use discord_rich_presence::{activity::{Activity, Assets, Button, Timestamps}, DiscordIpc, DiscordIpcClient};
|
||||
use serde::Serialize;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use crate::error::LauncherResult;
|
||||
|
|
@ -107,8 +106,8 @@ impl DiscordRPC {
|
|||
}
|
||||
}
|
||||
|
||||
#[onelauncher_macro::specta]
|
||||
#[derive(Debug, thiserror::Error, Serialize)]
|
||||
#[onelauncher_macro::error]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum DiscordError {
|
||||
#[error("Discord client ID is missing")]
|
||||
MissingClientId,
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ pub struct IngressProcessor {
|
|||
ingress_feeds: RwLock<HashMap<Uuid, Ingress>>,
|
||||
}
|
||||
|
||||
#[onelauncher_macro::specta]
|
||||
#[derive(Debug, thiserror::Error, Serialize)]
|
||||
#[onelauncher_macro::error]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum IngressError {
|
||||
#[error("ingress not found")]
|
||||
NotFound,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
|
||||
use interpulse::api::minecraft::VersionManifest as VanillaManifest;
|
||||
|
|
@ -8,7 +9,7 @@ use serde::de::DeserializeOwned;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::constants;
|
||||
use crate::error::LauncherResult;
|
||||
use crate::error::{LauncherError, LauncherResult};
|
||||
use crate::utils::http::fetch_json;
|
||||
use crate::utils::io;
|
||||
|
||||
|
|
@ -19,6 +20,7 @@ use super::Dirs;
|
|||
pub struct Metadata {
|
||||
initialized: bool,
|
||||
inner: MetadataInner,
|
||||
version_loader_cache: HashMap<String, Vec<GameLoader>>
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||
|
|
@ -31,8 +33,8 @@ struct MetadataInner {
|
|||
// legacyfabric: Option<ModdedManifest>,
|
||||
}
|
||||
|
||||
#[onelauncher_macro::specta]
|
||||
#[derive(Debug, thiserror::Error, Serialize)]
|
||||
#[onelauncher_macro::error]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum MetadataError {
|
||||
#[error("failed to fetch metadata")]
|
||||
FetchError,
|
||||
|
|
@ -41,7 +43,11 @@ pub enum MetadataError {
|
|||
#[error("loader {0} does not use a vanilla manifest")]
|
||||
NotVanillaManifest(GameLoader),
|
||||
#[error("failed to parse metadata: {0}")]
|
||||
ParseError(#[from] #[serde(skip)] serde_json::Error),
|
||||
ParseError(
|
||||
#[from]
|
||||
#[skip]
|
||||
serde_json::Error
|
||||
),
|
||||
#[error("no matching loader found")]
|
||||
NoMatchingLoader,
|
||||
#[error("no matching version found")]
|
||||
|
|
@ -70,9 +76,9 @@ impl Metadata {
|
|||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub async fn get_modded_or_fetch(&mut self, loader: GameLoader) -> LauncherResult<&ModdedManifest> {
|
||||
pub async fn get_modded_or_fetch(&mut self, loader: &GameLoader) -> LauncherResult<&ModdedManifest> {
|
||||
if !loader.is_modded() {
|
||||
return Err(MetadataError::NotModdedManifest(loader).into());
|
||||
return Err(MetadataError::NotModdedManifest(*loader).into());
|
||||
}
|
||||
|
||||
if !self.initialized() {
|
||||
|
|
@ -86,9 +92,9 @@ impl Metadata {
|
|||
self.inner.minecraft.as_ref().ok_or_else(|| MetadataError::FetchError.into())
|
||||
}
|
||||
|
||||
pub fn get_modded(&self, loader: GameLoader) -> LauncherResult<&ModdedManifest> {
|
||||
pub fn get_modded(&self, loader: &GameLoader) -> LauncherResult<&ModdedManifest> {
|
||||
if !loader.is_modded() {
|
||||
return Err(MetadataError::NotModdedManifest(loader).into());
|
||||
return Err(MetadataError::NotModdedManifest(*loader).into());
|
||||
}
|
||||
|
||||
match loader {
|
||||
|
|
@ -215,17 +221,48 @@ impl Metadata {
|
|||
(quilt, true)
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns a list of loaders that are compatible with the given Minecraft version.
|
||||
///
|
||||
/// WARNING: Can be heavy in certain cases!
|
||||
pub async fn get_loaders_for_version(&mut self, mc_version: &str) -> LauncherResult<Vec<GameLoader>> {
|
||||
if !self.initialized() {
|
||||
self.initialize().await?;
|
||||
}
|
||||
|
||||
if let Some(hit) = self.version_loader_cache.get(mc_version) {
|
||||
return Ok(hit.clone());
|
||||
}
|
||||
|
||||
let mut loaders = Vec::<GameLoader>::new();
|
||||
for loader in GameLoader::modded_loaders() {
|
||||
let manifest = match self.get_modded(loader) {
|
||||
Ok(manifest) => manifest,
|
||||
Err(LauncherError::MetadataError(MetadataError::NotModdedManifest(_))) => continue,
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
|
||||
let found = manifest.game_versions.iter().find(|it| it.id == mc_version);
|
||||
if found.is_some() {
|
||||
loaders.push(*loader);
|
||||
}
|
||||
}
|
||||
|
||||
self.version_loader_cache.insert(mc_version.to_owned(), loaders.clone());
|
||||
|
||||
Ok(loaders)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn fetch_vanilla_manifest(loader: GameLoader) -> LauncherResult<VanillaManifest> {
|
||||
async fn fetch_vanilla_manifest(loader: GameLoader) -> LauncherResult<VanillaManifest> {
|
||||
fetch_manifest(loader).await
|
||||
}
|
||||
|
||||
pub async fn fetch_modded_manifest(loader: GameLoader) -> LauncherResult<ModdedManifest> {
|
||||
async fn fetch_modded_manifest(loader: GameLoader) -> LauncherResult<ModdedManifest> {
|
||||
fetch_manifest(loader).await
|
||||
}
|
||||
|
||||
pub async fn fetch_manifest<T: DeserializeOwned>(loader: GameLoader) -> LauncherResult<T> {
|
||||
async fn fetch_manifest<T: DeserializeOwned>(loader: GameLoader) -> LauncherResult<T> {
|
||||
fetch_json::<T>(
|
||||
Method::GET,
|
||||
format!(
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ use crate::utils::io::IOError;
|
|||
use super::State;
|
||||
use super::credentials::MinecraftCredentials;
|
||||
|
||||
#[onelauncher_macro::specta]
|
||||
#[derive(Debug, thiserror::Error, Serialize)]
|
||||
#[onelauncher_macro::error]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum ProcessError {
|
||||
#[error("launch hook exited with non-zero code {0}")]
|
||||
HookUnsuccessful(i32),
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ use tokio::io::AsyncReadExt;
|
|||
|
||||
use super::io::IOError;
|
||||
|
||||
#[onelauncher_macro::specta]
|
||||
#[derive(Debug, thiserror::Error, Serialize)]
|
||||
#[onelauncher_macro::error]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum CryptoError {
|
||||
#[error("expected {algorithm} hash {expected}, but got {actual}")]
|
||||
InvalidHash {
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
|||
use tokio_util::compat::TokioAsyncWriteCompatExt;
|
||||
|
||||
/// A wrapper around generic and unhelpful [`std::io::Error`] messages.
|
||||
#[onelauncher_macro::specta]
|
||||
#[derive(Debug, thiserror::Error, Serialize)]
|
||||
#[onelauncher_macro::error]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum IOError {
|
||||
#[error("invalid absolute path '{0}'")]
|
||||
InvalidAbsolutePath(PathBuf),
|
||||
|
|
@ -22,16 +22,16 @@ pub enum IOError {
|
|||
#[error("error acessing path: {source}, path: {path}")]
|
||||
IOErrorWrapper {
|
||||
#[source]
|
||||
#[serde(skip)]
|
||||
#[skip]
|
||||
source: std::io::Error,
|
||||
path: String,
|
||||
},
|
||||
#[error(transparent)]
|
||||
IOError(#[from] #[serde(skip)] std::io::Error),
|
||||
IOError(#[from] #[skip] std::io::Error),
|
||||
#[error("json deserialization error: {0}")]
|
||||
DeserializeError(#[from] #[serde(skip)] serde_json::Error),
|
||||
DeserializeError(#[from] #[skip] serde_json::Error),
|
||||
#[error(transparent)]
|
||||
AsyncZipError(#[from] #[serde(skip)] async_zip::error::ZipError),
|
||||
AsyncZipError(#[from] #[skip] async_zip::error::ZipError),
|
||||
}
|
||||
|
||||
impl<P: AsRef<std::path::Path>> From<(P, std::io::Error)> for IOError {
|
||||
|
|
|
|||
|
|
@ -55,6 +55,16 @@ impl GameLoader {
|
|||
}
|
||||
}
|
||||
|
||||
pub const fn modded_loaders() -> &'static [Self] {
|
||||
&[
|
||||
Self::Forge,
|
||||
Self::NeoForge,
|
||||
Self::Quilt,
|
||||
Self::Fabric,
|
||||
Self::LegacyFabric,
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl TryFrom<String> for GameLoader {
|
||||
|
|
|
|||
179
packages/macro/src/error.rs
Normal file
179
packages/macro/src/error.rs
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
use proc_macro::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{parse_macro_input, Data, DeriveInput, Fields};
|
||||
|
||||
pub fn error_attr(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(item as DeriveInput);
|
||||
|
||||
let Data::Enum(data_enum) = &input.data else {
|
||||
return syn::Error::new_spanned(&input.ident, "Only enums are supported")
|
||||
.to_compile_error()
|
||||
.into();
|
||||
};
|
||||
|
||||
let ident = &input.ident;
|
||||
let mut serialize_arms = Vec::new();
|
||||
|
||||
for variant in &data_enum.variants {
|
||||
let v_ident = &variant.ident;
|
||||
match &variant.fields {
|
||||
Fields::Unit => {
|
||||
serialize_arms.push(quote! {
|
||||
Self::#v_ident => {
|
||||
let mut s = serializer.serialize_struct(stringify!(#ident), 2)?;
|
||||
s.serialize_field("type", stringify!(#v_ident))?;
|
||||
s.serialize_field("data", &self.to_string())?;
|
||||
s.end()
|
||||
}
|
||||
});
|
||||
}
|
||||
Fields::Unnamed(fields_unnamed) => {
|
||||
if fields_unnamed.unnamed.len() == 1 {
|
||||
let field = &fields_unnamed.unnamed[0];
|
||||
let mut has_from = false;
|
||||
let mut has_skip = false;
|
||||
|
||||
for attr in &field.attrs {
|
||||
if attr.path().is_ident("from") {
|
||||
has_from = true;
|
||||
} else if attr.path().is_ident("skip") {
|
||||
has_skip = true;
|
||||
}
|
||||
}
|
||||
|
||||
if has_from && !has_skip {
|
||||
serialize_arms.push(quote! {
|
||||
Self::#v_ident(inner) => {
|
||||
let mut s = serializer.serialize_struct(stringify!(#ident), 2)?;
|
||||
s.serialize_field("type", stringify!(#v_ident))?;
|
||||
s.serialize_field("data", inner)?;
|
||||
s.end()
|
||||
}
|
||||
});
|
||||
} else {
|
||||
serialize_arms.push(quote! {
|
||||
Self::#v_ident(_) => {
|
||||
let mut s = serializer.serialize_struct(stringify!(#ident), 2)?;
|
||||
s.serialize_field("type", stringify!(#v_ident))?;
|
||||
s.serialize_field("data", &self.to_string())?;
|
||||
s.end()
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
serialize_arms.push(quote! {
|
||||
Self::#v_ident(..) => {
|
||||
let mut s = serializer.serialize_struct(stringify!(#ident), 2)?;
|
||||
s.serialize_field("type", stringify!(#v_ident))?;
|
||||
s.serialize_field("data", &self.to_string())?;
|
||||
s.end()
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Fields::Named(_) => {
|
||||
serialize_arms.push(quote! {
|
||||
Self::#v_ident { .. } => {
|
||||
let mut s = serializer.serialize_struct(stringify!(#ident), 2)?;
|
||||
s.serialize_field("type", stringify!(#v_ident))?;
|
||||
s.serialize_field("data", &self.to_string())?;
|
||||
s.end()
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let serialize_impl = quote! {
|
||||
impl serde::Serialize for #ident {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::ser::Serializer,
|
||||
{
|
||||
use serde::ser::SerializeStruct;
|
||||
match self {
|
||||
#(#serialize_arms),*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let output = quote! {
|
||||
#[cfg_attr(feature = "specta", derive(onelauncher_macro::SerializedError))]
|
||||
#input
|
||||
|
||||
#serialize_impl
|
||||
};
|
||||
|
||||
output.into()
|
||||
}
|
||||
|
||||
pub fn error_derive(input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as DeriveInput);
|
||||
|
||||
let enum_name = &input.ident;
|
||||
let specta_name = format_ident!("{}SpectaType", enum_name);
|
||||
let mut variants = vec![];
|
||||
|
||||
let Data::Enum(data_enum) = &input.data else {
|
||||
return syn::Error::new_spanned(enum_name, "Only enums are supported")
|
||||
.to_compile_error()
|
||||
.into();
|
||||
};
|
||||
|
||||
for variant in &data_enum.variants {
|
||||
let name = &variant.ident;
|
||||
let ty = match &variant.fields {
|
||||
Fields::Unit => quote! { String },
|
||||
|
||||
Fields::Unnamed(fields) => {
|
||||
// Handle newtype-style or tuple-like enums
|
||||
if fields.unnamed.len() == 1 {
|
||||
let field = &fields.unnamed[0];
|
||||
let field_ty = &field.ty;
|
||||
|
||||
let has_from = field
|
||||
.attrs
|
||||
.iter()
|
||||
.any(|a| a.path().is_ident("from"));
|
||||
|
||||
let has_skip = field
|
||||
.attrs
|
||||
.iter()
|
||||
.any(|a| a.path().is_ident("skip"));
|
||||
|
||||
if has_from && !has_skip {
|
||||
quote! {
|
||||
#field_ty
|
||||
}
|
||||
} else {
|
||||
quote! { String }
|
||||
}
|
||||
} else {
|
||||
quote! { String }
|
||||
}
|
||||
}
|
||||
|
||||
Fields::Named(_) => {
|
||||
quote! { String } // Simplification: treat all struct-like variants as String
|
||||
}
|
||||
};
|
||||
|
||||
variants.push(quote! {
|
||||
#name(#ty)
|
||||
});
|
||||
}
|
||||
|
||||
let enum_name_str = enum_name.to_string();
|
||||
let output = quote! {
|
||||
#[derive(Debug, specta::Type, serde::Serialize)]
|
||||
#[specta(remote = #enum_name)]
|
||||
#[specta(tag = "type", content = "data")]
|
||||
#[specta(rename = #enum_name_str)]
|
||||
pub enum #specta_name {
|
||||
#(#variants,)*
|
||||
}
|
||||
};
|
||||
|
||||
output.into()
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
mod specta;
|
||||
|
||||
#[cfg(feature = "tauri")]
|
||||
mod tauri;
|
||||
mod error;
|
||||
|
||||
mod pin;
|
||||
|
||||
|
|
@ -14,13 +14,13 @@ mod pin;
|
|||
/// #[cfg_attr(feature = "specta", derive(specta::Type))]
|
||||
/// ```
|
||||
///
|
||||
/// ## `with_event` argument
|
||||
/// Add `#[specta(with_event)]` to add the `tauri_specta::Event` derive.
|
||||
/// ## `rename` attribute
|
||||
/// Add `rename = ''` attribute to rename the type.
|
||||
///
|
||||
/// #### Expands to:
|
||||
/// ```
|
||||
/// #[cfg_attr(feature = "specta", derive(specta::Type))]
|
||||
/// #[cfg_attr(feature = "tauri", derive(tauri_specta::Event))]
|
||||
/// #[cfg_attr(feature = "specta", specta(rename = #rename))]
|
||||
/// ```
|
||||
#[proc_macro_attribute]
|
||||
#[cfg(feature = "specta")]
|
||||
|
|
@ -28,16 +28,16 @@ pub fn specta(attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> p
|
|||
specta::specta(attr, item)
|
||||
}
|
||||
|
||||
/// This macro is used to derive the `tauri::command` as well as the `specta::specta` attribute for the annotated item.
|
||||
/// #### Expands to:
|
||||
/// ```
|
||||
/// #[specta::specta]
|
||||
/// #[tauri::command]
|
||||
/// ```
|
||||
/// This macro is used to implement the `serde::Serialize` trait for the annotated item.
|
||||
/// It only works for enums and tries to serialize them so that taurpc can use them properly.
|
||||
#[proc_macro_derive(SerializedError, attributes(from, skip))]
|
||||
pub fn serialized_error_derive(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
error::error_derive(item)
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
#[cfg(feature = "tauri")]
|
||||
pub fn command(attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
tauri::tauri_command(attr, item)
|
||||
pub fn error(attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
error::error_attr(attr, item)
|
||||
}
|
||||
|
||||
/// This macro Box::Pin a function
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
use quote::quote;
|
||||
use syn::{parse_macro_input, Item};
|
||||
|
||||
pub fn tauri_command(_attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let input = parse_macro_input!(item as Item);
|
||||
|
||||
let expanded = quote! {
|
||||
#[specta::specta]
|
||||
#[tauri::command]
|
||||
#input
|
||||
};
|
||||
|
||||
expanded.into()
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ use tokio::task::spawn_blocking;
|
|||
|
||||
/// A wrapper around generic and unhelpful [`std::io::Error`] messages.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[serde(tag = "type", content = "data")]
|
||||
pub enum IOError {
|
||||
/// A wrapped [`std::io::Error`] along with the path involved in the error.
|
||||
#[error("error acessing path: {source}, path: {path}")]
|
||||
|
|
@ -36,6 +37,7 @@ impl<P: AsRef<std::path::Path>> From<(P, std::io::Error)> for IOError {
|
|||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[serde(tag = "type", content = "data")]
|
||||
#[error("received a non UTF-8 path: <lossy_path='{}'>", .0.to_string_lossy())]
|
||||
pub struct NonUtf8PathError(pub Box<std::path::Path>);
|
||||
|
||||
|
|
|
|||
0
test.rs
Normal file
0
test.rs
Normal file
Loading…
Add table
Reference in a new issue