🔨 chore: some version bumps
Signed-off-by: Pauline <git@ethanlibs.co>
This commit is contained in:
parent
c5e96afc4c
commit
8ab0ea17cb
23 changed files with 1727 additions and 464 deletions
|
|
@ -6,6 +6,7 @@ indent_size = 4
|
|||
end_of_line = lf
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
|
||||
[*.nix]
|
||||
indent_style = space
|
||||
|
|
|
|||
16
.gitignore
vendored
16
.gitignore
vendored
|
|
@ -1,22 +1,6 @@
|
|||
# Nix
|
||||
result*
|
||||
repl-result-out*
|
||||
.direnv
|
||||
|
||||
# auto-generated files
|
||||
apps/frontend/src/bindings.ts
|
||||
apps/frontend/ipc
|
||||
|
||||
# Prisma
|
||||
crates/prisma/src/prisma.rs
|
||||
dev.db
|
||||
dev.db-journal
|
||||
|
||||
# Vendor
|
||||
.eslintcache
|
||||
# .env*
|
||||
vendor/
|
||||
vender/
|
||||
.cargo/config.toml
|
||||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/git,node,rust,yarn,linux,macos,windows,rust-analyzer,visualstudiocode,intellij+all
|
||||
|
|
|
|||
4
.npmrc
4
.npmrc
|
|
@ -1,5 +1,9 @@
|
|||
; make all engine requirements (e.g. node version) strictly kept
|
||||
engine-strict=true
|
||||
dedupe-peer-dependents=true
|
||||
# strict-peer-dependencies=true
|
||||
auto-install-peers=true
|
||||
max-old-space-size=4096
|
||||
enable-pre-post-scripts=true
|
||||
package-manager-strict=true
|
||||
package-manager-strict-version=true
|
||||
|
|
|
|||
11
.taplo.toml
Normal file
11
.taplo.toml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
[formatting]
|
||||
align_comments = true
|
||||
align_entries = true
|
||||
array_auto_collapse = true
|
||||
array_trailing_comma = true
|
||||
column_width = 100
|
||||
crlf = false
|
||||
indent_string = ' '
|
||||
reorder_arrays = true
|
||||
reorder_keys = true
|
||||
trailing_newline = true
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
pub mod macos;
|
||||
pub mod menu;
|
||||
pub mod updater;
|
||||
pub mod specta;
|
||||
|
|
|
|||
15
apps/desktop/src/ext/specta.rs
Normal file
15
apps/desktop/src/ext/specta.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
use std::io;
|
||||
use std::process::Command;
|
||||
use std::path::Path;
|
||||
|
||||
pub fn formatter(file: &Path) -> io::Result<()> {
|
||||
Command::new("pnpm")
|
||||
.arg("eslint")
|
||||
.arg("--fix")
|
||||
.arg(file)
|
||||
.output()
|
||||
.map(|_| ())
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))
|
||||
}
|
||||
|
||||
const _: specta_typescript::FormatterFn = formatter;
|
||||
|
|
@ -16,6 +16,7 @@ impl Update {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: tauri-specta event?
|
||||
#[derive(Default)]
|
||||
pub struct State {
|
||||
install_lock: Mutex<()>,
|
||||
|
|
|
|||
|
|
@ -48,7 +48,8 @@ pub async fn run_app<F: FnOnce(&tauri::AppHandle<tauri::Wry>) + Send + 'static>(
|
|||
prebuild
|
||||
.export(
|
||||
specta_typescript::Typescript::default()
|
||||
.bigint(specta_typescript::BigIntExportBehavior::BigInt),
|
||||
.bigint(specta_typescript::BigIntExportBehavior::BigInt)
|
||||
.formatter(crate::ext::specta::formatter),
|
||||
"../frontend/src/bindings.ts",
|
||||
)
|
||||
.expect("failed to export debug bindings!");
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@
|
|||
"sideEffects": false,
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build"
|
||||
"build": "vite build",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource/poppins": "^5.0.14",
|
||||
|
|
@ -22,7 +23,9 @@
|
|||
"@leeoniya/ufuzzy": "^1.0.14",
|
||||
"@onelauncher/client": "workspace:*",
|
||||
"@solid-primitives/refs": "^1.0.8",
|
||||
"@solidjs/router": "^0.14.1",
|
||||
"@solidjs/router": "^0.14.3",
|
||||
"@t3-oss/env-core": "^0.11.0",
|
||||
"zod": "^3.23.8",
|
||||
"@tanstack/solid-query": "^5.51.21",
|
||||
"@tauri-apps/api": "2.0.0-rc.0",
|
||||
"@tauri-apps/plugin-clipboard-manager": "github:tauri-apps/tauri-plugin-clipboard-manager#v2",
|
||||
|
|
@ -30,12 +33,12 @@
|
|||
"@tauri-apps/plugin-shell": "github:tauri-apps/tauri-plugin-shell#v2",
|
||||
"@thisbeyond/solid-dnd": "^0.7.5",
|
||||
"@thisbeyond/solid-select": "^0.15.0",
|
||||
"@unocss/reset": "^0.61.9",
|
||||
"@unocss/reset": "^0.62.1",
|
||||
"@untitled-theme/icons-solid": "^0.10.5",
|
||||
"overlayscrollbars": "^2.10.0",
|
||||
"overlayscrollbars-solid": "^0.5.5",
|
||||
"pathe": "^1.1.2",
|
||||
"solid-js": "^1.8.20",
|
||||
"solid-js": "^1.8.21",
|
||||
"solid-transition-group": "^0.2.3",
|
||||
"uuid": "^10.0.0"
|
||||
},
|
||||
|
|
@ -43,10 +46,11 @@
|
|||
"@solidjs/testing-library": "^0.8.9",
|
||||
"@tauri-apps/cli": "2.0.0-rc.3",
|
||||
"@testing-library/jest-dom": "^6.4.8",
|
||||
"@sentry/vite-plugin": "^2.22.2",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"jsdom": "^24.1.1",
|
||||
"sass": "^1.77.8",
|
||||
"unocss": "^0.61.9",
|
||||
"unocss": "^0.62.1",
|
||||
"vite-plugin-solid": "^2.10.2",
|
||||
"vite-plugin-solid-svg": "^0.8.1",
|
||||
"vite-tsconfig-paths": "^5.0.1"
|
||||
|
|
|
|||
858
apps/frontend/src/bindings.ts
Normal file
858
apps/frontend/src/bindings.ts
Normal file
|
|
@ -0,0 +1,858 @@
|
|||
|
||||
// This file was generated by [tauri-specta](https://github.com/oscartbeaumont/tauri-specta). Do not edit this file manually.
|
||||
|
||||
/** user-defined commands **/
|
||||
|
||||
|
||||
export const commands = {
|
||||
async authLogin(): Promise<Result<MinecraftCredentials | null, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("auth_login") };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async getUsers(): Promise<Result<MinecraftCredentials[], string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("get_users") };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async getUser(uuid: string): Promise<Result<MinecraftCredentials, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("get_user", { uuid }) };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async getDefaultUser(fallback: boolean | null): Promise<Result<MinecraftCredentials | null, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("get_default_user", { fallback }) };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async setDefaultUser(uuid: string | null): Promise<Result<null, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("set_default_user", { uuid }) };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async removeUser(uuid: string): Promise<Result<null, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("remove_user", { uuid }) };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async createCluster(props: CreateCluster): Promise<Result<string, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("create_cluster", { props }) };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Updates the cluster with the given UUID. The cluster only updates game setting fields
|
||||
*/
|
||||
async editGameSettings(uuid: string, newCluster: Cluster): Promise<Result<null, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("edit_game_settings", { uuid, newCluster }) };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async editClusterMeta(uuid: string, name: string | null, iconPath: string | null): Promise<Result<null, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("edit_cluster_meta", { uuid, name, iconPath }) };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async removeCluster(uuid: string): Promise<Result<null, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("remove_cluster", { uuid }) };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async getCluster(uuid: string): Promise<Result<Cluster, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("get_cluster", { uuid }) };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async getClusters(): Promise<Result<Cluster[], string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("get_clusters") };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async getClustersGrouped(): Promise<Result<{ [key in string]: Cluster[] }, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("get_clusters_grouped") };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async runCluster(uuid: string): Promise<Result<[string, number], string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("run_cluster", { uuid }) };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async getClusterLogs(uuid: string): Promise<Result<string[], string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("get_cluster_logs", { uuid }) };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async getClusterLog(uuid: string, logName: string): Promise<Result<string, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("get_cluster_log", { uuid, logName }) };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async uploadLog(uuid: string, logName: string): Promise<Result<string, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("upload_log", { uuid, logName }) };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async getScreenshots(uuid: string): Promise<Result<string[], string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("get_screenshots", { uuid }) };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async getWorlds(uuid: string): Promise<Result<string[], string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("get_worlds", { uuid }) };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async getRunningClusters(): Promise<Result<Cluster[], string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("get_running_clusters") };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async getProcessesByPath(path: ClusterPath): Promise<Result<string[], string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("get_processes_by_path", { path }) };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async killProcess(uuid: string): Promise<Result<null, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("kill_process", { uuid }) };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async isClusterRunning(uuid: string): Promise<Result<boolean, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("is_cluster_running", { uuid }) };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async getPidByUuid(uuid: string): Promise<Result<number, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("get_pid_by_uuid", { uuid }) };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async getSettings(): Promise<Result<Settings, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("get_settings") };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async setSettings(settings: Settings): Promise<Result<null, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("set_settings", { settings }) };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async getMinecraftVersions(): Promise<Result<Version[], string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("get_minecraft_versions") };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async randomMods(): Promise<Result<ManagedPackage[], string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("random_mods") };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async getMod(projectId: string): Promise<Result<ManagedPackage, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("get_mod", { projectId }) };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async downloadMod(clusterId: string, versionId: string): Promise<Result<null, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("download_mod", { clusterId, versionId }) };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async checkForUpdate(): Promise<Result<Update | null, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("check_for_update") };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async installUpdate(): Promise<Result<null, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("install_update") };
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** user-defined events **/
|
||||
|
||||
|
||||
export const events = __makeEvents__<{
|
||||
clusterPayload: ClusterPayload,
|
||||
ingressPayload: IngressPayload,
|
||||
internetPayload: InternetPayload,
|
||||
messagePayload: MessagePayload,
|
||||
offlinePayload: OfflinePayload,
|
||||
processPayload: ProcessPayload
|
||||
}>({
|
||||
clusterPayload: "cluster-payload",
|
||||
ingressPayload: "ingress-payload",
|
||||
internetPayload: "internet-payload",
|
||||
messagePayload: "message-payload",
|
||||
offlinePayload: "offline-payload",
|
||||
processPayload: "process-payload"
|
||||
})
|
||||
|
||||
/** user-defined constants **/
|
||||
|
||||
export const PROGRAM_INFO = { "arch": "64", "dev_build": true, "launcher_version": "1.0.0-alpha.1", "platform": "osx", "tauri_version": "2.0.0-rc.0", "webview_version": "19618.3.11.11.5" } as const;
|
||||
|
||||
/** user-defined types **/
|
||||
|
||||
/**
|
||||
* Represents a single Instance and installation of Minecraft
|
||||
* Contains settings and identifiers on a per-Cluster basis, falling back to default settings for Options<>
|
||||
*/
|
||||
export type Cluster = {
|
||||
/**
|
||||
* The Uuid of a specific cluster.
|
||||
*/
|
||||
uuid: string;
|
||||
/**
|
||||
* The download stage that of a cluster.
|
||||
*/
|
||||
stage?: ClusterStage;
|
||||
/**
|
||||
* The core path of the cluster.
|
||||
*/
|
||||
path?: string;
|
||||
/**
|
||||
* The associated cluster metadata.
|
||||
*/
|
||||
meta: ClusterMeta;
|
||||
/**
|
||||
* The per-cluster JVM memory allocation options.
|
||||
*/
|
||||
memory?: Memory | null;
|
||||
/**
|
||||
* The per-cluster JVM options.
|
||||
*/
|
||||
java?: JavaOptions | null;
|
||||
/**
|
||||
* The per-cluster Minecraft window default resolution.
|
||||
*/
|
||||
resolution?: Resolution | null;
|
||||
/**
|
||||
* The per-cluster Minecraft window fullscreen status.
|
||||
*/
|
||||
force_fullscreen: boolean | null; init_hooks?: InitHooks | null; packages: { [key in PackagePath]: Package }; update?: string | null
|
||||
}
|
||||
/**
|
||||
* Represents core Cluster metadata ([`Cluster#meta`]).
|
||||
*/
|
||||
export type ClusterMeta = {
|
||||
/**
|
||||
* The user-facing name of the cluster stored as a string.
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* The user-facing group of the cluster stored as a string.
|
||||
*/
|
||||
group?: string | null;
|
||||
/**
|
||||
* The associated Minecraft version of the cluster as last updated.
|
||||
*/
|
||||
mc_version: string;
|
||||
/**
|
||||
* The associated mod [`Loader`] as specified in the cluster.
|
||||
*/
|
||||
loader?: Loader;
|
||||
/**
|
||||
* The associated mod [`LoaderVersion`] if available.
|
||||
*/
|
||||
loader_version?: LoaderVersion | null;
|
||||
/**
|
||||
* The time that the cluster was created in [`DateTime<Utc>`].
|
||||
*/
|
||||
created_at?: string;
|
||||
/**
|
||||
* The time the cluster was last modified in [`DateTime<Utc>`].
|
||||
*/
|
||||
modified_at?: string;
|
||||
/**
|
||||
* The last time the cluster was played in [`DateTime<Utc>`].
|
||||
* (Defaults to None if the cluster has never been played)
|
||||
*/
|
||||
played_at?: string | null;
|
||||
/**
|
||||
* The overall time played in seconds stored as a [`u64`].
|
||||
*/
|
||||
overall_played?: bigint;
|
||||
/**
|
||||
* The recent time played stored as a [`u64`].
|
||||
*/
|
||||
recently_played?: bigint;
|
||||
/**
|
||||
* The associated [`PackageData`] and modpack data for the cluster.
|
||||
*/
|
||||
package_data?: PackageData | null;
|
||||
/**
|
||||
* The user-facing cluster icon as a [`PathBuf`].
|
||||
*/
|
||||
icon?: string | null;
|
||||
/**
|
||||
* The user-facing cluster icon as a URL string.
|
||||
*/
|
||||
icon_url?: string | null
|
||||
}
|
||||
/**
|
||||
* Relative Path wrapper to be used as an identifer for a cluster path.
|
||||
*/
|
||||
export type ClusterPath = string
|
||||
export type ClusterPayload = { uuid: string; cluster_path: ClusterPath; path: string; name: string; event: ClusterPayloadType }
|
||||
export type ClusterPayloadType = "created" | "inserted" | "synced" | "edited" | "deleted"
|
||||
/**
|
||||
* Core Cluster stages used in package logic.
|
||||
*/
|
||||
export type ClusterStage =
|
||||
/**
|
||||
* Installed with no downloads left.
|
||||
*/
|
||||
"installed" |
|
||||
/**
|
||||
* Downloading any sort of core metadata or mod file.
|
||||
*/
|
||||
"downloading" |
|
||||
/**
|
||||
* Downloading a full pack file, which is granted lower priority due to the high network demand.
|
||||
*/
|
||||
"pack_downloading" |
|
||||
/**
|
||||
* Not installed at all.
|
||||
*/
|
||||
"not_installed"
|
||||
export type CreateCluster = { name: string; mc_version: string; mod_loader: Loader; loader_version: string | null; icon: string | null; icon_url: string | null; package_data: PackageData | null; skip: boolean | null; skip_watch: boolean | null }
|
||||
export type IngressPayload = { event: IngressType; ingress_uuid: string; fraction: number | null; message: string }
|
||||
export type IngressType = { type: "initialize" } | { type: "download_java"; version: number } | { type: "download_loader"; cluster_path: string; cluster_name: string } | { type: "sync_cluster"; cluster_path: string; cluster_name: string } | { type: "copy_cluster"; import: string; cluster_name: string } | { type: "sync_config"; new_path: string } | { type: "archival"; cluster_path: string; cluster_name: string } | { type: "download_package"; cluster_path: string; package_name: string; icon: string | null; package_id: string | null; package_version: string | null } | { type: "download_pack"; cluster_path: string; package_name: string; icon: string | null; package_version: string }
|
||||
/**
|
||||
* Global initialization hooks for all Minecraft clusters.
|
||||
*/
|
||||
export type InitHooks = {
|
||||
/**
|
||||
* Pre-launch hook.
|
||||
*/
|
||||
pre?: string | null;
|
||||
/**
|
||||
* Wrapper hook for the runtime of the game instance.
|
||||
*/
|
||||
wrapper?: string | null;
|
||||
/**
|
||||
* Post-launch hook.
|
||||
*/
|
||||
post?: string | null
|
||||
}
|
||||
export type InternetPayload = { event: "InstallPackage"; id: string } | { event: "InstallPack"; id: string } | { event: "InstallPath"; path: string }
|
||||
/**
|
||||
* Custom Java arguments on a per-cluster basis.
|
||||
*/
|
||||
export type JavaOptions = {
|
||||
/**
|
||||
* A custom java version from the global java store, if specified.
|
||||
*/
|
||||
custom_version?: JavaVersion | null;
|
||||
/**
|
||||
* Custom runtime arguments when running the cluster.
|
||||
*/
|
||||
custom_arguments?: string[] | null;
|
||||
/**
|
||||
* Custom environment variables when running the cluster.
|
||||
*/
|
||||
custom_env_arguments?: ([string, string])[] | null
|
||||
}
|
||||
/**
|
||||
* A struct representing a single version of the Java Runtime Environment.
|
||||
* Use [`locate_java`] to get an array of all located java instances on the machine.
|
||||
*
|
||||
* common java paths from https://github.com/PrismLauncher/PrismLauncher/blob/develop/launcher/java/JavaUtils.cpp under GPL 3.0
|
||||
*
|
||||
* java check functionality from https://github.com/modrinth/theseus/blob/master/theseus/src/util/jre.rs under MIT
|
||||
*/
|
||||
export type JavaVersion = { version: string; arch: string; path: string }
|
||||
/**
|
||||
* A HashMap of all located and installed available Java versions
|
||||
*/
|
||||
export type JavaVersions = { [key in string]: JavaVersion }
|
||||
/**
|
||||
* Available mod loaders to be used for a cluster.
|
||||
*/
|
||||
export type Loader =
|
||||
/**
|
||||
* The default vanilla loader, no modding supported.
|
||||
*/
|
||||
"vanilla" |
|
||||
/**
|
||||
* The MinecraftForge Minecraft mod loader.
|
||||
*/
|
||||
"forge" |
|
||||
/**
|
||||
* The FabircMC Minecraft mod loader.
|
||||
*/
|
||||
"fabric" |
|
||||
/**
|
||||
* The NeoForge Minecraft mod loader.
|
||||
*/
|
||||
"neoforge" |
|
||||
/**
|
||||
* The Quilt Minecraft mod loader.
|
||||
*/
|
||||
"quilt" |
|
||||
/**
|
||||
* The Legacy Fabric port mod loader.
|
||||
*/
|
||||
"legacyfabric"
|
||||
/**
|
||||
* A version of a Minecraft mod loader
|
||||
*/
|
||||
export type LoaderVersion = {
|
||||
/**
|
||||
* The version ID of the loader
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* The URL of the version's manifest
|
||||
*/
|
||||
url: string;
|
||||
/**
|
||||
* Whether the loader is stable or not
|
||||
*/
|
||||
stable: boolean
|
||||
}
|
||||
/**
|
||||
* Universal interface for managed package dependencies.
|
||||
*/
|
||||
export type ManagedDependency = { version_id: string | null; package_id: string | null; file_name: string | null; dependency_type: PackageDependency }
|
||||
/**
|
||||
* Universal metadata for any managed package from a Mod distribution platform.
|
||||
*/
|
||||
export type ManagedPackage = { id: string; uid: string | null; package_type: PackageType; title: string; description: string; main: string; versions: string[]; game_versions: string[]; loaders: string[]; icon_url: string | null; created: string; updated: string; client: PackageSide; server: PackageSide; downloads: number; followers: number; categories: string[]; optional_categories: string[] | null }
|
||||
/**
|
||||
* Universal interface for managed package authors and users.
|
||||
*/
|
||||
export type ManagedUser = { id: string; role: string; username: string; name: string | null; avatar: string | null; description: string | null; created: string }
|
||||
/**
|
||||
* Universal managed package version of a package.
|
||||
*/
|
||||
export type ManagedVersion = { id: string; package_id: string; author: string; name: string; featured: boolean; version_id: string; changelog: string; changelog_url: string | null; published: string; downloads: number; version_type: string; files: ManagedVersionFile[]; deps: ManagedDependency[]; game_versions: string[]; loaders: string[] }
|
||||
/**
|
||||
* Universal interface for managed package files.
|
||||
*/
|
||||
export type ManagedVersionFile = { url: string; file_name: string; primary: boolean; size: number; file_type: PackageFile | null; hashes: { [key in string]: string } }
|
||||
/**
|
||||
* Global memory settings across all clusters.
|
||||
*/
|
||||
export type Memory = {
|
||||
/**
|
||||
* Maximum amount of Java memory available globally.
|
||||
*/
|
||||
maximum: number;
|
||||
/**
|
||||
* Minimum amount of Java memory available globally.
|
||||
*/
|
||||
minimum: number
|
||||
}
|
||||
export type MessagePayload = { message: string }
|
||||
/**
|
||||
* 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 OfflinePayload = { offline: boolean }
|
||||
/**
|
||||
* A struct that represents a Package.
|
||||
*/
|
||||
export type Package = { sha512: string; meta: PackageMetadata; file_name: string; disabled: boolean }
|
||||
/**
|
||||
* Optional data used to link a specific cluster to a package project.
|
||||
*/
|
||||
export type PackageData = {
|
||||
/**
|
||||
* The package ID as a String.
|
||||
*/
|
||||
package_id: string | null;
|
||||
/**
|
||||
* The version of the package as a String.
|
||||
*/
|
||||
version_id: string | null;
|
||||
/**
|
||||
* Whether or not the current package is locked (for legacy modpack support).
|
||||
*/
|
||||
locked?: boolean | null
|
||||
}
|
||||
/**
|
||||
* The type of a [`ManagedDependency`].
|
||||
*/
|
||||
export type PackageDependency = "Required" | "Optional" | "Incompatible" | "Embedded"
|
||||
/**
|
||||
* The file type of a [`Package`].
|
||||
*/
|
||||
export type PackageFile = "required_pack" | "optional_pack" | "unknown"
|
||||
/**
|
||||
* Metadata that represents a [`Package`].
|
||||
*/
|
||||
export type PackageMetadata = { type: "managed"; package: ManagedPackage; version: ManagedVersion; users: ManagedUser; update: ManagedVersion | null; incompatible: boolean } | { type: "mapped"; title: string | null; description: string | null; authors: string[]; version: string | null; icon: string | null; package_type: string | null } | { type: "unknown" }
|
||||
/**
|
||||
* Relative [`PathBuf`] for a specific [`Package`] of a [`Cluster`].
|
||||
*/
|
||||
export type PackagePath = string
|
||||
/**
|
||||
* The Client/Server side type of a [`Package`].
|
||||
*/
|
||||
export type PackageSide = "required" | "optional" | "unsupported" | "unknown"
|
||||
/**
|
||||
* Represents types of packages handled by the launcher.
|
||||
*/
|
||||
export type PackageType =
|
||||
/**
|
||||
* represents a mod jarfile
|
||||
*/
|
||||
"mod" |
|
||||
/**
|
||||
* represents a datapack file
|
||||
*/
|
||||
"datapack" |
|
||||
/**
|
||||
* represents a resourcepack file
|
||||
*/
|
||||
"resource" |
|
||||
/**
|
||||
* represents a shaderpack file
|
||||
*/
|
||||
"shader"
|
||||
export type ProcessPayload = { uuid: string; pid: number; event: ProcessPayloadType; message: string }
|
||||
export type ProcessPayloadType = "started" | "modified" | "finished"
|
||||
/**
|
||||
* Global Minecraft resolution.
|
||||
*/
|
||||
export type Resolution = [number, number]
|
||||
/**
|
||||
* A global settings state for the launcher.
|
||||
*/
|
||||
export type Settings = {
|
||||
/**
|
||||
* A OneLauncher [`Theme`] managed by the core GUI.
|
||||
*/
|
||||
theme: Theme;
|
||||
/**
|
||||
* Does not ask for confirmation when closing the OneLauncher GUI
|
||||
*/
|
||||
hide_close_prompt?: boolean;
|
||||
/**
|
||||
* Disables animations in the OneLauncher GUI
|
||||
*/
|
||||
disable_animations?: boolean;
|
||||
/**
|
||||
* A global fullscreen Minecraft state.
|
||||
*/
|
||||
force_fullscreen?: boolean;
|
||||
/**
|
||||
* A global default [`Resolution`] for Minecraft.
|
||||
*/
|
||||
resolution: Resolution;
|
||||
/**
|
||||
* A global [`JavaVersions`] list and default version.
|
||||
*/
|
||||
java_versions: JavaVersions;
|
||||
/**
|
||||
* A global [`Memory`] settings store for Java memory settings.
|
||||
*/
|
||||
memory: Memory;
|
||||
/**
|
||||
* Global and default initialization hooks .
|
||||
*/
|
||||
init_hooks: InitHooks;
|
||||
/**
|
||||
* Global and default custom Java arguments.
|
||||
*/
|
||||
custom_java_args: string[];
|
||||
/**
|
||||
* Global and default custom environment variables.
|
||||
*/
|
||||
custom_env_args: ([string, string])[];
|
||||
/**
|
||||
* Global and default maximum [`Semaphore`] I/O operations.
|
||||
*/
|
||||
max_async_io_operations: bigint;
|
||||
/**
|
||||
* Global and default maximum [`Semaphore`] HTTP operations.
|
||||
*/
|
||||
max_async_fetches: bigint;
|
||||
/**
|
||||
* The [`CURRENT_FORMAT_VERSION`] of this settings file.
|
||||
*/
|
||||
version: number;
|
||||
/**
|
||||
* Whether or not to disable Discord IPC.
|
||||
*/
|
||||
disable_discord?: boolean;
|
||||
/**
|
||||
* Whether or not to enable a debug mode in the launcher.
|
||||
*/
|
||||
debug_mode?: boolean;
|
||||
/**
|
||||
* Whether or not to disable Plausible and Sentry analytics.
|
||||
*/
|
||||
disable_analytics?: boolean;
|
||||
/**
|
||||
* The core global config directory stored as a [`PathBuf`].
|
||||
*/
|
||||
config_dir?: string | null;
|
||||
/**
|
||||
* Whether or not to minimize the launcher upon a game launch.
|
||||
*/
|
||||
hide_on_launch?: boolean;
|
||||
/**
|
||||
* Enable/disable advanced rendering and window decorations.
|
||||
*/
|
||||
rendering?: boolean
|
||||
}
|
||||
/**
|
||||
* A OneLauncher theme managed by the GUI.
|
||||
*/
|
||||
export type Theme =
|
||||
/**
|
||||
* A default Dark theme.
|
||||
*/
|
||||
"dark" |
|
||||
/**
|
||||
* A default Light theme.
|
||||
*/
|
||||
"light" |
|
||||
/**
|
||||
* OLED Dark Theme.
|
||||
*/
|
||||
"contrast" |
|
||||
/**
|
||||
* Cute and colorful theme.
|
||||
*/
|
||||
"cat"
|
||||
export type Update = { version: string }
|
||||
/**
|
||||
* A game version of Minecraft
|
||||
*/
|
||||
export type Version = {
|
||||
/**
|
||||
* A unique identifier of the version
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* The release type of the version
|
||||
*/
|
||||
type: VersionType;
|
||||
/**
|
||||
* A link to additional information about the version
|
||||
*/
|
||||
url: string;
|
||||
/**
|
||||
* The latest time a file in this version was updated
|
||||
*/
|
||||
time: string;
|
||||
/**
|
||||
* The time this version was released
|
||||
*/
|
||||
releaseTime: string;
|
||||
/**
|
||||
* The SHA1 hash of the additional information about the version
|
||||
*/
|
||||
sha1: string;
|
||||
/**
|
||||
* Whether the version supports the latest player safety features
|
||||
*/
|
||||
complianceLevel: number;
|
||||
/**
|
||||
* The SHA1 hash of the original unmodified Minecraft version's JSON
|
||||
* This is only available when using the Pulseflow mirror
|
||||
*/
|
||||
originalSha1?: string | null
|
||||
}
|
||||
/**
|
||||
* The version type
|
||||
*/
|
||||
export type VersionType =
|
||||
/**
|
||||
* A major version, which is stable for all players to use
|
||||
*/
|
||||
"release" |
|
||||
/**
|
||||
* An experimental version, which is unstable and used for feature previews and beta testing
|
||||
*/
|
||||
"snapshot" |
|
||||
/**
|
||||
* The oldest versions before the game was released
|
||||
*/
|
||||
"old_alpha" |
|
||||
/**
|
||||
* Early versions of the game
|
||||
*/
|
||||
"old_beta"
|
||||
|
||||
/** tauri-specta globals **/
|
||||
|
||||
import {
|
||||
invoke as TAURI_INVOKE,
|
||||
Channel as TAURI_CHANNEL,
|
||||
} from "@tauri-apps/api/core";
|
||||
import * as TAURI_API_EVENT from "@tauri-apps/api/event";
|
||||
import { type WebviewWindow as __WebviewWindow__ } from "@tauri-apps/api/webviewWindow";
|
||||
|
||||
type __EventObj__<T> = {
|
||||
listen: (
|
||||
cb: TAURI_API_EVENT.EventCallback<T>,
|
||||
) => ReturnType<typeof TAURI_API_EVENT.listen<T>>;
|
||||
once: (
|
||||
cb: TAURI_API_EVENT.EventCallback<T>,
|
||||
) => ReturnType<typeof TAURI_API_EVENT.once<T>>;
|
||||
emit: T extends null
|
||||
? (payload?: T) => ReturnType<typeof TAURI_API_EVENT.emit>
|
||||
: (payload: T) => ReturnType<typeof TAURI_API_EVENT.emit>;
|
||||
};
|
||||
|
||||
export type Result<T, E> =
|
||||
| { status: "ok"; data: T }
|
||||
| { status: "error"; error: E };
|
||||
|
||||
function __makeEvents__<T extends Record<string, any>>(
|
||||
mappings: Record<keyof T, string>,
|
||||
) {
|
||||
return new Proxy(
|
||||
{} as unknown as {
|
||||
[K in keyof T]: __EventObj__<T[K]> & {
|
||||
(handle: __WebviewWindow__): __EventObj__<T[K]>;
|
||||
};
|
||||
},
|
||||
{
|
||||
get: (_, event) => {
|
||||
const name = mappings[event as keyof T];
|
||||
|
||||
return new Proxy((() => { }) as any, {
|
||||
apply: (_, __, [window]: [__WebviewWindow__]) => ({
|
||||
listen: (arg: any) => window.listen(name, arg),
|
||||
once: (arg: any) => window.once(name, arg),
|
||||
emit: (arg: any) => window.emit(name, arg),
|
||||
}),
|
||||
get: (_, command: keyof __EventObj__<any>) => {
|
||||
switch (command) {
|
||||
case "listen":
|
||||
return (arg: any) => TAURI_API_EVENT.listen(name, arg);
|
||||
case "once":
|
||||
return (arg: any) => TAURI_API_EVENT.once(name, arg);
|
||||
case "emit":
|
||||
return (arg: any) => TAURI_API_EVENT.emit(name, arg);
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@ import { createStore } from 'solid-js/store';
|
|||
import { Transition } from 'solid-transition-group';
|
||||
import Button from '../base/Button';
|
||||
import FullscreenOverlay from './FullscreenOverlay';
|
||||
import type { MakeOptional } from '~types.ts';
|
||||
import type { MakeOptional } from '~types';
|
||||
|
||||
type ModalsList = (() => JSX.Element)[];
|
||||
|
||||
|
|
|
|||
12
apps/frontend/src/utils/environment.ts
Normal file
12
apps/frontend/src/utils/environment.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { createEnv } from '@t3-oss/env-core';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const env = createEnv({
|
||||
clientPrefix: 'VITE_',
|
||||
client: {
|
||||
VITE_LANDING_ORIGIN: z.string().default('https://polyfrost.org'),
|
||||
},
|
||||
runtimeEnv: import.meta.env,
|
||||
skipValidation: false,
|
||||
emptyStringAsUndefined: true,
|
||||
});
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import type { Cluster, Loader, VersionType } from '~bindings';
|
||||
|
||||
export * from './PausableTimer';
|
||||
export * from './timer';
|
||||
export * from './sorting';
|
||||
|
||||
export function supportsMods(loader?: Cluster | Loader): boolean {
|
||||
|
|
|
|||
12
apps/frontend/src/utils/query.ts
Normal file
12
apps/frontend/src/utils/query.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { QueryClient } from '@tanstack/solid-query';
|
||||
|
||||
export const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
networkMode: 'always',
|
||||
},
|
||||
mutations: {
|
||||
networkMode: 'always',
|
||||
}
|
||||
}
|
||||
});
|
||||
79
apps/frontend/src/utils/updater.tsx
Normal file
79
apps/frontend/src/utils/updater.tsx
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
import { listen } from '@tauri-apps/api/event';
|
||||
import { commands } from '~bindings';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
__LAUNCHER_UPDATER__?: true;
|
||||
__ONELAUNCHER_VERSION__: string;
|
||||
}
|
||||
}
|
||||
|
||||
export type Update = { version: string };
|
||||
export type UpdateStore =
|
||||
| { status: 'idle' }
|
||||
| { status: 'loading' }
|
||||
| { status: 'error' }
|
||||
| { status: 'updateAvailable'; update: Update }
|
||||
| { status: 'noUpdateAvailable' }
|
||||
| { status: 'installing' };
|
||||
|
||||
export function createUpdater() {
|
||||
if (!window.__LAUNCHER_UPDATER__) return;
|
||||
|
||||
const updateStore: UpdateStore = { status: 'idle' };
|
||||
listen<UpdateStore>('updater', e => Object.assign(updateStore, e.payload));
|
||||
const onInstallCallbacks = new Set<() => void>();
|
||||
|
||||
async function checkForUpdate() {
|
||||
const result = await commands.checkForUpdate();
|
||||
|
||||
if (result.status === 'error') {
|
||||
console.error('[updater]: ', result.error);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!result.data)
|
||||
return null;
|
||||
|
||||
// TODO: ui
|
||||
// TODO: cb
|
||||
|
||||
return result.data;
|
||||
}
|
||||
|
||||
function installUpdate() {
|
||||
for (const cb of onInstallCallbacks) cb();
|
||||
// TODO: ui/toast
|
||||
return commands.installUpdate();
|
||||
}
|
||||
|
||||
const ONELAUNCHER_VERSION_LOCALSTORAGE = 'onelauncher-version';
|
||||
async function updatedCheck() {
|
||||
const version = window.__ONELAUNCHER_VERSION__;
|
||||
const lastVersion = localStorage.getItem(ONELAUNCHER_VERSION_LOCALSTORAGE);
|
||||
const updaterStore = { tagline: null };
|
||||
|
||||
if (!lastVersion) return;
|
||||
|
||||
if (lastVersion !== version) {
|
||||
localStorage.setItem(ONELAUNCHER_VERSION_LOCALSTORAGE, version);
|
||||
|
||||
try {
|
||||
const req = await fetch(`${import.meta.env.VITE_LANDING_ORIGIN}/api/releases/${version}`);
|
||||
const { frontmatter } = await req.json();
|
||||
updaterStore.tagline = frontmatter?.tagline;
|
||||
} catch (error) {
|
||||
console.warn('[updater]: failed to fetch release info');
|
||||
console.error('[updater]: ', error);
|
||||
}
|
||||
|
||||
// TODO: ui/toast/popup
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
checkForUpdate,
|
||||
installUpdate,
|
||||
updatedCheck,
|
||||
};
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ import solid from 'vite-plugin-solid';
|
|||
import solidSvg from 'vite-plugin-solid-svg';
|
||||
import paths from 'vite-tsconfig-paths';
|
||||
import unocss from 'unocss/vite';
|
||||
import sentry from '@sentry/vite-plugin';
|
||||
|
||||
export default defineConfig(async ({ mode }) => {
|
||||
process.env = { ...process.env, ...loadEnv(mode, process.cwd(), '') };
|
||||
|
|
@ -35,11 +36,15 @@ export default defineConfig(async ({ mode }) => {
|
|||
server: {
|
||||
port: 8001,
|
||||
strictPort: true,
|
||||
watch: {
|
||||
ignored: ['**/src-tauri/**'],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
if (process.env.SENTRY_AUTH_TOKEN)
|
||||
config.plugins.push(sentry.sentryVitePlugin({
|
||||
authToken: process.env.SENTRY_AUTH_TOKEN,
|
||||
org: 'polyfrost',
|
||||
project: 'onelauncher_frontend',
|
||||
}));
|
||||
|
||||
return config;
|
||||
});
|
||||
|
|
|
|||
16
package.json
16
package.json
|
|
@ -4,7 +4,7 @@
|
|||
"version": "1.0.0-alpha.1",
|
||||
"private": true,
|
||||
"engineStrict": true,
|
||||
"packageManager": "pnpm@9.7.0",
|
||||
"packageManager": "pnpm@9.7.1",
|
||||
"description": "Next-generation open source Minecraft launcher and tools for interacting with Polyfrost",
|
||||
"license": "GPL-3.0-only",
|
||||
"homepage": "https://polyfrost.org",
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
"bugs": "https://github.com/polyfrost/onelauncher/issues",
|
||||
"sideEffects": false,
|
||||
"engines": {
|
||||
"pnpm": "9.7.0",
|
||||
"pnpm": "9.7.1",
|
||||
"npm": "pnpm",
|
||||
"yarn": "pnpm",
|
||||
"node": ">=18"
|
||||
|
|
@ -35,7 +35,6 @@
|
|||
"core": "cd packages/core && cargo",
|
||||
"testing": "cd apps/testing && cargo",
|
||||
"tauri": "cd apps/desktop && cargo",
|
||||
|
||||
"test:vi": "pnpm vitest run",
|
||||
"test:update": "pnpm vitest -u",
|
||||
"test:ui": "pnpm vitest --ui",
|
||||
|
|
@ -52,18 +51,19 @@
|
|||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@flowr/eslint-config": "^3.11.3",
|
||||
"@types/node": "^22.2.0",
|
||||
"@unocss/eslint-plugin": "^0.61.9",
|
||||
"@flowr/eslint-config": "^3.11.5",
|
||||
"@types/node": "^22.3.0",
|
||||
"@unocss/eslint-plugin": "^0.62.1",
|
||||
"@vitest/ui": "^2.0.5",
|
||||
"bumpp": "^9.4.2",
|
||||
"bumpp": "^9.5.1",
|
||||
"@taplo/cli": "^0.7.0",
|
||||
"eslint": "^9.9.0",
|
||||
"eslint-plugin-solid": "^0.14.1",
|
||||
"jiti": "^1.21.6",
|
||||
"ts-node": "^10.9.2",
|
||||
"tsx": "~4.17.0",
|
||||
"typescript": "^5.5.4",
|
||||
"vite": "^5.4.0",
|
||||
"vite": "^5.4.1",
|
||||
"vitest": "^2.0.5"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
"@tanstack/solid-query": "^5.51.21",
|
||||
"fast-equals": "^5.0.1",
|
||||
"plausible-tracker": "^0.3.9",
|
||||
"solid-js": "^1.8.20",
|
||||
"solid-js": "^1.8.21",
|
||||
"zod": "^3.23.8"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@
|
|||
"int:prepare": "pnpm tsx prepare.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@flowr/utils": "^3.11.3",
|
||||
"execa": "^9.3.0",
|
||||
"@flowr/utils": "^3.11.5",
|
||||
"execa": "^9.3.1",
|
||||
"mustache": "^4.2.0",
|
||||
"pathe": "^1.1.2",
|
||||
"semver": "^7.6.3",
|
||||
|
|
|
|||
1127
pnpm-lock.yaml
generated
1127
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue