clan ui: setup typed api method

This commit is contained in:
Johannes Kirschbauer
2024-05-20 19:34:27 +02:00
parent 6ebfd29c87
commit 8687801cee
16 changed files with 375 additions and 96 deletions

View File

@@ -1,22 +1,74 @@
const deserialize = (fn: Function) => (str: string) => {
try {
fn(JSON.parse(str));
} catch (e) {
alert(`Error parsing JSON: ${e}`);
}
};
import { FromSchema } from "json-schema-to-ts";
import { schema } from "@/api";
export const PYAPI = {
list_machines: {
dispatch: (data: null) =>
// @ts-ignore
type API = FromSchema<typeof schema>;
type OperationNames = keyof API;
type OperationArgs<T extends OperationNames> = API[T]["argument"];
type OperationResponse<T extends OperationNames> = API[T]["return"];
declare global {
interface Window {
clan: {
[K in OperationNames]: (str: string) => void;
};
webkit: {
messageHandlers: {
gtk: {
postMessage: (message: { method: OperationNames; data: any }) => void;
};
};
};
}
}
function createFunctions<K extends OperationNames>(
operationName: K
): {
dispatch: (args: OperationArgs<K>) => void;
receive: (fn: (response: OperationResponse<K>) => void) => void;
} {
return {
dispatch: (args: OperationArgs<K>) => {
console.log(
`Operation: ${operationName}, Arguments: ${JSON.stringify(args)}`
);
// Send the data to the gtk app
window.webkit.messageHandlers.gtk.postMessage({
method: "list_machines",
data,
}),
receive: (fn: (response: string[]) => void) => {
// @ts-ignore
method: operationName,
data: args,
});
},
receive: (fn: (response: OperationResponse<K>) => void) => {
window.clan.list_machines = deserialize(fn);
},
},
};
}
const operations = schema.properties;
const operationNames = Object.keys(operations) as OperationNames[];
type PyApi = {
[K in OperationNames]: {
dispatch: (args: OperationArgs<K>) => void;
receive: (fn: (response: OperationResponse<K>) => void) => void;
};
};
const deserialize =
<T>(fn: (response: T) => void) =>
(str: string) => {
try {
fn(JSON.parse(str) as T);
} catch (e) {
alert(`Error parsing JSON: ${e}`);
}
};
// Create the API object
const pyApi: PyApi = {} as PyApi;
operationNames.forEach((name) => {
pyApi[name] = createFunctions(name);
});
export { pyApi };