Add transport-agnostic RPC layer for proxy app

Introduces yaak-rpc (shared RPC infrastructure) and yaak-proxy-lib
(proxy app logic decoupled from any frontend). A single Tauri command
dispatches all RPC calls through a typed router, with TypeScript types
auto-generated via ts-rs and a generic rpc() function for type-safe
calls from the frontend.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Gregory Schier
2026-03-08 11:27:51 -07:00
parent 4c37e62146
commit 6f8c4c06bb
11 changed files with 332 additions and 67 deletions

View File

@@ -0,0 +1,81 @@
use serde::{Deserialize, Serialize};
use std::sync::Mutex;
use ts_rs::TS;
use yaak_proxy::ProxyHandle;
use yaak_rpc::{RpcError, define_rpc};
// -- Context shared across all RPC handlers --
pub struct ProxyCtx {
handle: Mutex<Option<ProxyHandle>>,
}
impl ProxyCtx {
pub fn new() -> Self {
Self {
handle: Mutex::new(None),
}
}
}
// -- Request/response types --
#[derive(Deserialize, TS)]
#[ts(export, export_to = "gen_rpc.ts")]
pub struct ProxyStartRequest {
pub port: Option<u16>,
}
#[derive(Serialize, TS)]
#[ts(export, export_to = "gen_rpc.ts")]
#[serde(rename_all = "camelCase")]
pub struct ProxyStartResponse {
pub port: u16,
pub already_running: bool,
}
#[derive(Deserialize, TS)]
#[ts(export, export_to = "gen_rpc.ts")]
pub struct ProxyStopRequest {}
// -- Handlers --
fn proxy_start(ctx: &ProxyCtx, req: ProxyStartRequest) -> Result<ProxyStartResponse, RpcError> {
let mut handle = ctx
.handle
.lock()
.map_err(|_| RpcError { message: "lock poisoned".into() })?;
if let Some(existing) = handle.as_ref() {
return Ok(ProxyStartResponse {
port: existing.port,
already_running: true,
});
}
let proxy_handle = yaak_proxy::start_proxy(req.port.unwrap_or(0))
.map_err(|e| RpcError { message: e })?;
let port = proxy_handle.port;
*handle = Some(proxy_handle);
Ok(ProxyStartResponse {
port,
already_running: false,
})
}
fn proxy_stop(ctx: &ProxyCtx, _req: ProxyStopRequest) -> Result<bool, RpcError> {
let mut handle = ctx
.handle
.lock()
.map_err(|_| RpcError { message: "lock poisoned".into() })?;
Ok(handle.take().is_some())
}
// -- Router + Schema --
define_rpc! {
ProxyCtx;
"proxy_start" => proxy_start(ProxyStartRequest) -> ProxyStartResponse,
"proxy_stop" => proxy_stop(ProxyStopRequest) -> bool,
}