Skip to content

Instantly share code, notes, and snippets.

@kaylendog
Last active May 28, 2023 14:30
Show Gist options
  • Save kaylendog/ea3d2ff8607d8433849c6bd431fb39b0 to your computer and use it in GitHub Desktop.
Save kaylendog/ea3d2ff8607d8433849c6bd431fb39b0 to your computer and use it in GitHub Desktop.
Workaround for `window` issue in `@tauri-apps/api`
import {
NoOpTransport,
OperationType,
randomId,
RSPCError,
} from "@rspc/client";
import type { UnlistenFn } from "@tauri-apps/api/event";
/**
* Workaround for https://github.com/tauri-apps/tauri/issues/6226. Since NextJS
* executes all code on the server, simply importing the Tauri API will cause
* an error.
*/
export class ClientTauriTransport extends NoOpTransport {
private requestMap = new Map<string, (data: any) => void>();
private listener?: Promise<UnlistenFn | null>;
clientSubscriptionCallback?: (id: string, value: any) => void;
constructor() {
super();
import("@tauri-apps/api").then((tauri) => {
this.listener = tauri.event
.listen("plugin:rspc:transport:resp", (event) => {
const { id, result } = event.payload as any;
if (result.type === "event") {
if (this.clientSubscriptionCallback)
this.clientSubscriptionCallback(id, result.data);
} else if (result.type === "response") {
if (this.requestMap.has(id)) {
this.requestMap.get(id)?.({
type: "response",
result: result.data,
});
this.requestMap.delete(id);
}
} else if (result.type === "error") {
const { message, code } = result.data;
if (this.requestMap.has(id)) {
this.requestMap.get(id)?.({ type: "error", message, code });
this.requestMap.delete(id);
}
} else {
console.error(`Received event of unknown method '${result.type}'`);
}
})
.catch((err) => {
console.warn(
"Error while creating Tauri transport listener. If we aren't running in a Tauri webview, you can ignore this.",
err
);
return null;
});
});
}
async doRequest(
operation: OperationType,
key: string,
input: string
): Promise<any> {
if (this.listener) {
await this.listener;
}
const id = randomId();
let resolve: (data: any) => void;
const promise = new Promise((res) => {
resolve = res;
});
// @ts-ignore
this.requestMap.set(id, resolve);
const appWindow = await import("@tauri-apps/api").then(
(tauri) => tauri.window.appWindow
);
await appWindow.emit("plugin:rspc:transport", {
id,
method: operation,
params: {
path: key,
input,
},
});
const body = (await promise) as any;
if (body.type === "error") {
const { code, message } = body;
throw new RSPCError(code, message);
} else if (body.type === "response") {
return body.result;
} else {
throw new Error(
`RSPC Tauri doRequest received invalid body type '${body?.type}'`
);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment