diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 00000000..1f64a473
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 00000000..79ee123c
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
index 82f51e21..ce318a47 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,7 +4,6 @@ members = [
"core",
"debugger",
"desktop/src-tauri",
- "testing",
]
[workspace.package]
@@ -33,7 +32,7 @@ tauri-plugin-updater = { git = "https://github.com/tauri-apps/plugins-workspace"
rspc = { version = "0.2.0", features = [ "specta2" ] }
specta = { version = "=2.0.0-rc.12" }
-tauri-specta = { version = "=2.0.0-rc.9", features = [
+tauri-specta = { version = "=2.0.0-rc.10", features = [
"javascript",
"typescript"
] }
diff --git a/core/Cargo.toml b/core/Cargo.toml
index 1b3dfa49..c36a56f0 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -14,12 +14,22 @@ authors = { workspace = true }
default = []
# feature flag allowing us to interact with tauri (for loading animations, errors showing on gui, etc)
# also allows us to compile onelauncher core without tauri
-tauri = [ "dep:tauri" ]
+tauri = [
+ "dep:tauri",
+ "dep:tauri-specta",
+ "dep:specta"
+]
cli = [ "dep:indicatif" ]
[dependencies]
onelauncher_debug = { path = "../debugger" }
+
+# GUI-only deps
tauri = { workspace = true, optional = true }
+tauri-specta = { workspace = true, optional = true }
+specta = { workspace = true, optional = true }
+
+# CLI-only deps
indicatif = { workspace = true, optional = true }
interpulse = { workspace = true }
diff --git a/desktop/.gitignore b/desktop/.gitignore
index b3bed89e..e0be417d 100644
--- a/desktop/.gitignore
+++ b/desktop/.gitignore
@@ -1,2 +1,3 @@
/dist-isolation
/coverage
+./src/bindings.ts
diff --git a/desktop/src-tauri/Cargo.toml b/desktop/src-tauri/Cargo.toml
index c0675306..60c8bb32 100644
--- a/desktop/src-tauri/Cargo.toml
+++ b/desktop/src-tauri/Cargo.toml
@@ -41,6 +41,9 @@ tauri-plugin-single-instance = { workspace = true }
tauri-plugin-updater = { workspace = true }
tauri-plugin-authenticator = { workspace = true }
+tauri-specta = { workspace = true }
+specta = { workspace = true }
+
tokio = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
diff --git a/desktop/src-tauri/src/api/commands.rs b/desktop/src-tauri/src/api/commands.rs
new file mode 100644
index 00000000..4c3e5382
--- /dev/null
+++ b/desktop/src-tauri/src/api/commands.rs
@@ -0,0 +1,43 @@
+use tauri_specta::{Builder, ExportLanguage};
+use crate::api;
+
+#[macro_export]
+macro_rules! collect_commands {
+ () => {
+ {
+ use crate::api::commands::*;
+ tauri_specta::ts::builder()
+ .commands(tauri_specta::collect_commands![
+ initialize_state,
+ is_dev
+ ])
+ }
+ };
+}
+
+pub fn test() -> Builder {
+ use crate::api::commands::*;
+ tauri_specta::ts::builder()
+ .commands(tauri_specta::collect_commands![
+ initialize_state,
+ is_dev
+ ])
+}
+
+#[specta::specta]
+#[tracing::instrument(skip_all)]
+#[tauri::command]
+pub async fn initialize_state(app: tauri::AppHandle) -> api::Result<()> {
+ onelauncher::ProxyState::initialize(app).await?;
+ let s = onelauncher::State::get().await?;
+ onelauncher::State::update();
+
+ s.processor.write().await.restore().await?;
+ Ok(())
+}
+
+#[specta::specta]
+#[tauri::command]
+pub fn is_dev() -> bool {
+ cfg!(debug_assertions)
+}
\ No newline at end of file
diff --git a/desktop/src-tauri/src/api/mod.rs b/desktop/src-tauri/src/api/mod.rs
index 786c5af2..d67bc477 100644
--- a/desktop/src-tauri/src/api/mod.rs
+++ b/desktop/src-tauri/src/api/mod.rs
@@ -4,6 +4,8 @@ use tauri::plugin::TauriPlugin;
use tauri::Manager;
use tokio::sync::Mutex;
+pub mod commands;
+
pub fn init() -> TauriPlugin {
tauri::plugin::Builder::new("onelauncher")
.setup(|app, _| {
@@ -11,14 +13,31 @@ pub fn init() -> TauriPlugin {
Ok(())
})
- .invoke_handler(tauri::generate_handler![])
.build()
}
pub type Result = std::result::Result;
-#[derive(thiserror::Error, Debug)]
+#[derive(thiserror::Error, Debug, Serialize, specta::Type)]
pub enum OneLauncherSerializableError {
+ #[error("{0}")]
+ CommonError(String),
+}
+
+impl From for OneLauncherSerializableError {
+ fn from(value: OneLauncherError) -> Self {
+ Self::CommonError(value.to_string())
+ }
+}
+
+impl From for OneLauncherSerializableError {
+ fn from(value: onelauncher::Error) -> Self {
+ Self::CommonError(value.to_string())
+ }
+}
+
+#[derive(thiserror::Error, Debug)]
+pub enum OneLauncherError {
#[error("{0}")]
OneLauncher(#[from] onelauncher::Error),
@@ -37,14 +56,14 @@ pub enum OneLauncherSerializableError {
// (yoinked under MIT license)
macro_rules! impl_serialize_err {
($($variant:ident),* $(,)?) => {
- impl Serialize for OneLauncherSerializableError {
+ impl Serialize for OneLauncherError {
fn serialize(&self, serializer: S) -> std::result::Result
where
S: Serializer,
{
use serde::ser::SerializeStruct;
match self {
- OneLauncherSerializableError::OneLauncher(onelauncher_error) => {
+ OneLauncherError::OneLauncher(onelauncher_error) => {
$crate::error::display_tracing_error(onelauncher_error);
let mut state = serializer.serialize_struct("OneLauncher", 2)?;
@@ -53,7 +72,7 @@ macro_rules! impl_serialize_err {
state.end()
}
$(
- OneLauncherSerializableError::$variant(message) => {
+ OneLauncherError::$variant(message) => {
let mut state = serializer.serialize_struct(stringify!($variant), 2)?;
state.serialize_field("field_name", stringify!($variant))?;
state.serialize_field("message", &message.to_string())?;
diff --git a/desktop/src-tauri/src/lib.rs b/desktop/src-tauri/src/lib.rs
index cd9136c2..93a699ea 100644
--- a/desktop/src-tauri/src/lib.rs
+++ b/desktop/src-tauri/src/lib.rs
@@ -1,25 +1,10 @@
use tauri::Manager;
+use crate::api::commands;
pub mod api;
pub mod error;
pub mod ext;
-// #[tracing::instrument(skip_all)]
-// #[tauri::command]
-// async fn initialize_state(app: tauri::AppHandle) -> api::Result<()> {
-// onelauncher::ProxyState::initialize(app).await?;
-// let s = onelauncher::State::get().await?;
-// onelauncher::State::update();
-
-// s.processor.write().await.restore().await?;
-// Ok(())
-// }
-
-#[tauri::command]
-fn is_dev() -> bool {
- cfg!(debug_assertions)
-}
-
#[derive(Clone, serde::Serialize)]
struct SingleInstancePayload {
args: Vec,
@@ -33,7 +18,7 @@ pub async fn run() {
let _log_guard = onelauncher::start_logger();
tracing::info!("initialized tracing subscriber. loading onelauncher...");
- run_app(tauri::Builder::default(), |app| {
+ run_app(|app| {
if let Err(err) = setup(app) {
tracing::error!("failed to setup app: {:?}", err);
}
@@ -41,11 +26,10 @@ pub async fn run() {
.await;
}
-pub async fn run_app) + Send + 'static>(
- builder: tauri::Builder,
+pub async fn run_app(
setup: F,
) {
- let builder = builder
+ let builder = tauri::Builder::default()
.plugin(tauri_plugin_shell::init())
.plugin(tauri_plugin_single_instance::init(|app, argv, cwd| {
println!("{}, {argv:?}, {cwd}", app.package_info().name);
@@ -55,7 +39,7 @@ pub async fn run_app) + Send + '
.plugin(tauri_plugin_updater::Builder::new().build())
.plugin(ext::updater::plugin())
.manage(ext::updater::State::default())
- // .plugin(tauri_plugin_window_state::Builder::default().build())
+ .plugin(tauri_plugin_window_state::Builder::default().build())
.menu(tauri::menu::Menu::new)
.setup(move |app| {
setup(app);
@@ -64,10 +48,14 @@ pub async fn run_app) + Send + '
let builder = builder
.plugin(api::init())
- .invoke_handler(tauri::generate_handler![
- // initialize_state,
- is_dev,
- ]);
+ .invoke_handler({
+ let builder = commands::test();
+
+ #[cfg(debug_assertions)]
+ let builder = builder.path("../src/bindings.ts");
+
+ builder.build().unwrap()
+ });
let app = builder
.build(tauri::tauri_build_context!())
diff --git a/desktop/src/bindings.ts b/desktop/src/bindings.ts
new file mode 100644
index 00000000..0f5b5bcb
--- /dev/null
+++ b/desktop/src/bindings.ts
@@ -0,0 +1,80 @@
+ // This file was generated by [tauri-specta](https://github.com/oscartbeaumont/tauri-specta). Do not edit this file manually.
+
+ export const commands = {
+async initializeState() : Promise> {
+try {
+ return { status: "ok", data: await TAURI_INVOKE("initialize_state") };
+} catch (e) {
+ if(e instanceof Error) throw e;
+ else return { status: "error", error: e as any };
+}
+},
+async isDev() : Promise {
+return await TAURI_INVOKE("is_dev");
+}
+}
+
+
+
+/** user-defined types **/
+
+export type OneLauncherSerializableError = { CommonError: string }
+
+/** tauri-specta globals **/
+
+ import { invoke as TAURI_INVOKE } 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__ = {
+ listen: (
+ cb: TAURI_API_EVENT.EventCallback
+ ) => ReturnType>;
+ once: (
+ cb: TAURI_API_EVENT.EventCallback
+ ) => ReturnType>;
+ emit: T extends null
+ ? (payload?: T) => ReturnType
+ : (payload: T) => ReturnType;
+};
+
+export type Result =
+ | { status: "ok"; data: T }
+ | { status: "error"; error: E };
+
+function __makeEvents__>(
+ mappings: Record
+) {
+ return new Proxy(
+ {} as unknown as {
+ [K in keyof T]: __EventObj__ & {
+ (handle: __WebviewWindow__): __EventObj__;
+ };
+ },
+ {
+ 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__) => {
+ 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);
+ }
+ },
+ });
+ },
+ }
+ );
+}
+
+
\ No newline at end of file