69 lines
1.8 KiB
TypeScript
69 lines
1.8 KiB
TypeScript
/**
|
|
* Thin bridge over the Tauri JS API. Everything is dynamically imported so the
|
|
* web bundle never pulls in `@tauri-apps/*` and `pnpm build` (web) keeps
|
|
* working even if the native packages are absent.
|
|
*/
|
|
import { isTauriRuntime } from "@/lib/platform"
|
|
|
|
type InvokeFn = <T>(cmd: string, args?: Record<string, unknown>) => Promise<T>
|
|
type ListenFn = (
|
|
event: string,
|
|
handler: (e: { payload: unknown }) => void
|
|
) => Promise<() => void>
|
|
|
|
let invokeImpl: InvokeFn | null = null
|
|
let listenImpl: ListenFn | null = null
|
|
|
|
async function loadCore(): Promise<InvokeFn | null> {
|
|
if (!isTauriRuntime()) return null
|
|
if (invokeImpl) return invokeImpl
|
|
try {
|
|
const mod = (await import("@tauri-apps/api/core")) as { invoke: InvokeFn }
|
|
invokeImpl = mod.invoke
|
|
return invokeImpl
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
async function loadEvent(): Promise<ListenFn | null> {
|
|
if (!isTauriRuntime()) return null
|
|
if (listenImpl) return listenImpl
|
|
try {
|
|
const mod = (await import("@tauri-apps/api/event")) as { listen: ListenFn }
|
|
listenImpl = mod.listen
|
|
return listenImpl
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
/** Invoke a Tauri command. Returns null (no-op) outside a Tauri webview or on timeout. */
|
|
export async function invoke<T>(
|
|
cmd: string,
|
|
args?: Record<string, unknown>
|
|
): Promise<T | null> {
|
|
const fn = await loadCore()
|
|
if (!fn) return null
|
|
try {
|
|
return await Promise.race([
|
|
fn<T>(cmd, args),
|
|
new Promise<never>((_, reject) => {
|
|
setTimeout(() => reject(new Error("invoke_timeout")), 5_000)
|
|
}),
|
|
])
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
/** Subscribe to a Tauri event. Returns an unsubscribe fn (no-op on web). */
|
|
export async function listen(
|
|
event: string,
|
|
handler: (payload: unknown) => void
|
|
): Promise<() => void> {
|
|
const fn = await loadEvent()
|
|
if (!fn) return () => {}
|
|
return fn(event, (e) => handler(e.payload))
|
|
}
|