Generate TypeScript Client for IPC¶
Info
This is an experimental feature. You may also encounter some bugsβplease report them on GitHub issues!
Since v0.7
, pytauri natively supports generating a TypeScript client for Commands. This makes calling pytauri commands in TypeScript very simple and type-safe.
Install Dependencies¶
pytauri uses pydantic to generate jsonschema, then calls json-schema-to-typescript to convert it into TypeScript type definitions.
Install the dependencies with the following commands:
Usage Example¶
Commands.experimental_gen_ts_background
from os import getenv
from pathlib import Path
from anyio.from_thread import start_blocking_portal
from pydantic import BaseModel, ConfigDict
from pydantic.alias_generators import to_camel
from pytauri import (
Commands,
builder_factory,
context_factory,
)
# β You should only enable this feature in development (not production)
PYTAURI_GEN_TS = getenv("PYTAURI_GEN_TS") != "0"
# β Enable this feature first
commands = Commands(experimental_gen_ts=PYTAURI_GEN_TS)
class _BaseModel(BaseModel):
model_config = ConfigDict(
# Accepts camelCase js ipc arguments for snake_case python fields.
#
# See: <https://docs.pydantic.dev/2.10/concepts/alias/#using-an-aliasgenerator>
alias_generator=to_camel,
# By default, pydantic allows unknown fields,
# which results in TypeScript types having `[key: string]: unknown`.
#
# See: <https://docs.pydantic.dev/2.10/concepts/models/#extra-data>
extra="forbid",
)
class Person(_BaseModel):
"""A simple model representing a person.
@property name - The name of the person.
"""
# π This pydoc will be converted to tsdoc
name: str
# β Just use `commands` as usual
@commands.command()
async def greet_to_person(body: Person) -> str:
"""A simple command that returns a greeting message.
@param body - The person to greet.
"""
# π This pydoc will be converted to tsdoc
return f"Hello, {body.name}!"
def main() -> int:
with start_blocking_portal("asyncio") as portal:
if PYTAURI_GEN_TS:
# β Generate TypeScript Client to your frontend `src/client` directory
output_dir = Path(__file__).parent.parent.parent.parent / "src" / "client"
# β The CLI to run `json-schema-to-typescript`,
# `--format=false` is optional to improve performance
json2ts_cmd = "pnpm json2ts --format=false"
# β Start the background task to generate TypeScript types
portal.start_task_soon(
lambda: commands.experimental_gen_ts_background(
output_dir, json2ts_cmd, cmd_alias=to_camel
)
)
app = builder_factory().build(
context=context_factory(),
invoke_handler=commands.generate_handler(portal),
)
exit_code = app.run_return()
return exit_code
When you run your app (pnpm tauri dev
), the TypeScript client code will be generated in the src/client
directory:
Tip
Every time you modify a command, the TypeScript client code will automatically update after hot reload. Awesome π!
/* eslint-disable */
/**
* This file was automatically generated by pytauri-gen-ts.
* DO NOT MODIFY IT BY HAND. Instead, modify the source commands API,
* and run pytauri-gen-ts to regenerate this file.
*/
import { pyInvoke } from "tauri-plugin-pytauri-api";
import { InvokeOptions } from "@tauri-apps/api/core";
import type { Commands } from "./_apiTypes.d.ts";
/**
* A simple command that returns a greeting message.
*
* @param body - The person to greet.
*/
export async function greetToPerson(
body: Commands["greet_to_person"]["input"],
options?: InvokeOptions
): Promise<Commands["greet_to_person"]["output"]> {
return await pyInvoke("greet_to_person", body, options);
}
FAQ¶
JS Channel
and PY JavaScriptChannelId
Type Mismatch¶
Argument of type 'Channel<unknown>' is not assignable to parameter of type 'string'.ts(2345)
JavaScriptChannelId is serialized and deserialized as a string
between the frontend and backend, so the generated ts type is string
.
You just need to pass Channel.toJSON()
(i.e., JSON.stringify(Channel)
):
import { Channel } from "@tauri-apps/api/core";
const channel = new Channel();
await fooCmd(channel.toJSON()); // pass the channel as a string
This is a known limitation, but we don't know how to solve it yet. If you have a good suggestion, please open a GitHub issue π.
How to Generate TS Types for Event
and Channel
?¶
Not supported yet. We haven't figured out an ergonomic API. If you have a good suggestion, please open a GitHub issue π.