Skip to content

Commit 8bb49f4

Browse files
committed
queries/mutations docs
1 parent 4b93c6d commit 8bb49f4

3 files changed

Lines changed: 81 additions & 31 deletions

File tree

examples/tanstack-query/src-tauri/src/main.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use thiserror::Error;
1313

1414
// -- Types --
1515

16+
/// A user of the application.
1617
#[derive(Serialize, Deserialize, Type, Clone)]
1718
pub struct User {
1819
id: u32,
@@ -21,6 +22,7 @@ pub struct User {
2122
}
2223

2324
#[derive(Serialize, Deserialize, Type, Clone)]
25+
/// A todo item associated with a user.
2426
pub struct Todo {
2527
id: u32,
2628
title: String,
@@ -36,6 +38,7 @@ pub struct AppState {
3638

3739
pub type AppStateMutex = Mutex<AppState>;
3840

41+
/// A simple API error type for demonstration purposes.
3942
#[derive(Error, Debug, Serialize, Type)]
4043
#[serde(tag = "type", content = "data")]
4144
pub enum ApiError {
@@ -47,6 +50,9 @@ pub enum ApiError {
4750

4851
// -- Queries (read operations) --
4952

53+
/// Get a user by ID.
54+
///
55+
/// Returns an error if the user does not exist.
5056
#[tauri::command]
5157
#[specta::specta]
5258
fn get_user(state: tauri::State<AppStateMutex>, id: u32) -> Result<User, ApiError> {
@@ -59,13 +65,17 @@ fn get_user(state: tauri::State<AppStateMutex>, id: u32) -> Result<User, ApiErro
5965
.ok_or(ApiError::NotFound(format!("User {id} not found")))
6066
}
6167

68+
/// List all users.
6269
#[tauri::command]
6370
#[specta::specta]
6471
fn list_users(state: tauri::State<AppStateMutex>) -> Vec<User> {
6572
let state = state.lock().unwrap();
6673
state.users.clone()
6774
}
6875

76+
/// List todos for a specific user, optionally filtering by title.
77+
///
78+
/// If `title` is provided, only todos containing that substring are returned.
6979
#[tauri::command]
7080
#[specta::specta]
7181
fn list_todos(
@@ -121,6 +131,7 @@ fn create_todo(
121131
Ok(todo)
122132
}
123133

134+
/// Delete a user by ID, returning an error if the user does not exist.
124135
#[tauri::command]
125136
#[specta::specta]
126137
fn delete_user(state: tauri::State<AppStateMutex>, id: u32) -> Result<(), ApiError> {
@@ -133,6 +144,7 @@ fn delete_user(state: tauri::State<AppStateMutex>, id: u32) -> Result<(), ApiErr
133144
}
134145
}
135146

147+
/// Delete a todo by ID, returning an error if the todo does not exist.
136148
#[tauri::command]
137149
#[specta::specta]
138150
fn delete_todo(state: tauri::State<AppStateMutex>, id: u32) -> Result<(), ApiError> {

examples/tanstack-query/src/bindings.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,25 @@ import { queryOptions as __TANSTACK_QUERY_OPTIONS, mutationOptions as __TANSTACK
55

66
/** Commands */
77
export const commands = {
8+
/**
9+
* Get a user by ID.
10+
*
11+
* Returns an error if the user does not exist.
12+
*/
813
getUser: (id: number) => typedError<User, ApiError>(__TAURI_INVOKE("get_user", { id })),
14+
// List all users.
915
listUsers: () => __TAURI_INVOKE<User[]>("list_users"),
16+
/**
17+
* List todos for a specific user, optionally filtering by title.
18+
*
19+
* If `title` is provided, only todos containing that substring are returned.
20+
*/
1021
listTodos: (userId: number, title: string | null) => __TAURI_INVOKE<Todo[]>("list_todos", { userId, title }),
1122
createUser: (name: string, email: string) => typedError<User, ApiError>(__TAURI_INVOKE("create_user", { name, email })),
1223
createTodo: (title: string, userId: number) => typedError<Todo, ApiError>(__TAURI_INVOKE("create_todo", { title, userId })),
24+
// Delete a user by ID, returning an error if the user does not exist.
1325
deleteUser: (id: number) => typedError<null, ApiError>(__TAURI_INVOKE("delete_user", { id })),
26+
// Delete a todo by ID, returning an error if the todo does not exist.
1427
deleteTodo: (id: number) => typedError<null, ApiError>(__TAURI_INVOKE("delete_todo", { id })),
1528
};
1629

@@ -23,8 +36,19 @@ export const queryKeys = {
2336

2437
/** Queries */
2538
export const queries = {
39+
/**
40+
* Get a user by ID.
41+
*
42+
* Returns an error if the user does not exist.
43+
*/
2644
getUser: (id: number) => __TANSTACK_QUERY_OPTIONS<User, ApiError>({ queryKey: queryKeys.getUser(id), queryFn: () => unwrapTypedError(commands.getUser(id)) }),
45+
// List all users.
2746
listUsers: () => __TANSTACK_QUERY_OPTIONS<User[]>({ queryKey: queryKeys.listUsers(), queryFn: () => commands.listUsers() }),
47+
/**
48+
* List todos for a specific user, optionally filtering by title.
49+
*
50+
* If `title` is provided, only todos containing that substring are returned.
51+
*/
2852
listTodos: (userId: number, title: string | null) => __TANSTACK_QUERY_OPTIONS<Todo[]>({ queryKey: queryKeys.listTodos(userId, title), queryFn: () => commands.listTodos(userId, title) }),
2953
};
3054

@@ -40,20 +64,25 @@ export const mutationKeys = {
4064
export const mutations = {
4165
createUser: () => __TANSTACK_MUTATION_OPTIONS<User, ApiError, { name: string, email: string }>({ mutationKey: mutationKeys.createUser(), mutationFn: ({ name, email }: { name: string, email: string }) => unwrapTypedError(commands.createUser(name, email)) }),
4266
createTodo: () => __TANSTACK_MUTATION_OPTIONS<Todo, ApiError, { title: string, userId: number }>({ mutationKey: mutationKeys.createTodo(), mutationFn: ({ title, userId }: { title: string, userId: number }) => unwrapTypedError(commands.createTodo(title, userId)) }),
67+
// Delete a user by ID, returning an error if the user does not exist.
4368
deleteUser: () => __TANSTACK_MUTATION_OPTIONS<null, ApiError, { id: number }>({ mutationKey: mutationKeys.deleteUser(), mutationFn: ({ id }: { id: number }) => unwrapTypedError(commands.deleteUser(id)) }),
69+
// Delete a todo by ID, returning an error if the todo does not exist.
4470
deleteTodo: () => __TANSTACK_MUTATION_OPTIONS<null, ApiError, { id: number }>({ mutationKey: mutationKeys.deleteTodo(), mutationFn: ({ id }: { id: number }) => unwrapTypedError(commands.deleteTodo(id)) }),
4571
};
4672

4773
/* Types */
74+
// A simple API error type for demonstration purposes.
4875
export type ApiError = { type: "NotFound"; data: string } | { type: "Internal"; data: string };
4976

77+
// A todo item associated with a user.
5078
export type Todo = {
5179
id: number,
5280
title: string,
5381
completed: boolean,
5482
user_id: number,
5583
};
5684

85+
// A user of the application.
5786
export type User = {
5887
id: number,
5988
name: string,

src/lang/js_ts.rs

Lines changed: 40 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -307,31 +307,7 @@ fn runtime(
307307

308308
let mut field = Field::new(define(format!("({fn_arguments}) => {body}")).into());
309309
field.set_deprecated(command.deprecated().cloned());
310-
field.set_docs({
311-
let mut docs = command.docs().to_string();
312-
313-
if jsdoc {
314-
if !docs.is_empty() {
315-
docs.push('\n');
316-
}
317-
318-
docs.push_str(
319-
&arguments
320-
.iter()
321-
.map(|(name, dt)| format!("@param {{{dt}}} {name}"))
322-
.collect::<Vec<_>>()
323-
.join("\n"),
324-
);
325-
326-
if !arguments.is_empty() {
327-
docs.push('\n');
328-
}
329-
330-
docs.push_str("@returns {string} myName");
331-
}
332-
333-
docs.into()
334-
});
310+
field.set_docs(build_command_docs(command, &arguments, jsdoc));
335311
s = s.field(command.name().to_lower_camel_case(), field);
336312
}
337313

@@ -403,8 +379,10 @@ fn runtime(
403379
"({fn_arguments}) => __TANSTACK_QUERY_OPTIONS{generics}({{ queryKey: queryKeys.{command_name}({call_args}), queryFn: () => {query_fn_body} }})"
404380
);
405381

406-
queries_struct = queries_struct
407-
.field(command_name.clone(), Field::new(define(query_body).into()));
382+
let mut field = Field::new(define(query_body).into());
383+
field.set_deprecated(command.deprecated().cloned());
384+
field.set_docs(build_command_docs(command, &arguments, jsdoc));
385+
queries_struct = queries_struct.field(command_name.clone(), field);
408386
}
409387

410388
emit_struct_export(
@@ -478,10 +456,10 @@ fn runtime(
478456
"() => __TANSTACK_MUTATION_OPTIONS{generics}({{ mutationKey: mutationKeys.{command_name}(), mutationFn: ({mutation_fn_param}) => {mutation_fn_body} }})"
479457
);
480458

481-
mutations_struct = mutations_struct.field(
482-
command_name.clone(),
483-
Field::new(define(mutation_body).into()),
484-
);
459+
let mut field = Field::new(define(mutation_body).into());
460+
field.set_deprecated(command.deprecated().cloned());
461+
field.set_docs(build_command_docs(command, &arguments, jsdoc));
462+
mutations_struct = mutations_struct.field(command_name.clone(), field);
485463
}
486464

487465
emit_struct_export(
@@ -623,6 +601,37 @@ fn runtime(
623601
Ok(Cow::Owned(out))
624602
}
625603

604+
/// Build the doc comment for a command, including `@param` annotations for each argument if `jsdoc` is true.
605+
fn build_command_docs(
606+
command: &Function,
607+
arguments: &[(String, String)],
608+
jsdoc: bool,
609+
) -> Cow<'static, str> {
610+
let mut docs = command.docs().to_string();
611+
612+
if jsdoc {
613+
if !docs.is_empty() {
614+
docs.push('\n');
615+
}
616+
617+
docs.push_str(
618+
&arguments
619+
.iter()
620+
.map(|(name, dt)| format!("@param {{{dt}}} {name}"))
621+
.collect::<Vec<_>>()
622+
.join("\n"),
623+
);
624+
625+
if !arguments.is_empty() {
626+
docs.push('\n');
627+
}
628+
629+
docs.push_str("@returns {string} myName");
630+
}
631+
632+
docs.into()
633+
}
634+
626635
/// Collect command arguments as (camelCase name, rendered type) pairs.
627636
fn collect_arguments(
628637
command: &Function,

0 commit comments

Comments
 (0)