Skip to content

feat(resolution): link imported Tauri invokes to registered Rust commands - #2524

Closed
nk33-dev wants to merge 1 commit into
colbymchenry:mainfrom
nk33-dev:codex/tauri-ipc-links
Closed

nk33-dev wants to merge 1 commit into
colbymchenry:mainfrom
nk33-dev:codex/tauri-ipc-links

Conversation

@nk33-dev

Copy link
Copy Markdown

Problem

The existing Tauri decorator recognition keeps command functions from being reported as dead code, but it does not connect a frontend invoke("command") to the Rust handler. That leaves a cross-language call-path gap.

Changes

  • Add a Rust + JS-family-gated synthesis pass for conventional src-tauri/src apps.
  • Require a Tauri API import, static invoke key, decorated Rust function, and registration through tauri::Builder::default().invoke_handler(tauri::generate_handler![...]). This follows the documented command registration.
  • Parse import/call/macro AST nodes instead of using comments or string contents as registration proof.
  • Preserve invoke line/column and handler-registration evidence on heuristic edges.
  • Track registration/import inputs for incremental rebuilding; reject shadows, duplicate command keys and cross-app matches.

Validation

Windows / Node 24, upstream baseline 7ba8eee4:

  • npx tsc --noEmit: passed.
  • Tauri precision/sync suite: 10 passed (direct/alias/namespace imports, module paths, shadows, dynamic/absent keys, comment/string decoys, app isolation, duplicate keys, same-line ownership and registration removal/restoration).
  • Existing synthesis progress/scaling regressions: 5 passed.
  • git diff --check: passed.

Review Status / Limits

Draft: required small/medium/large real-repo probes and Sonnet agent A/B have not been run; fixture success is not full framework validation. No full test suite was run.

This does not model global Tauri access, wrappers/re-exports, aliased Rust macros, builder variables, nonstandard crate/module layouts or Vue/Svelte script extraction. Registration is source evidence, not a runtime permission/reachability claim. No schema, extraction or kernel changes.

@colbymchenry

Copy link
Copy Markdown
Owner

Thanks for this, @nk33-dev! It links Tauri invoke calls to Rust commands, and #878 builds the same bridge, validated on three real apps. Your check that a command is really registered through generate_handler! is a good one. Closing this in favor of #878.

colbymchenry added a commit that referenced this pull request Oct 31, 2026
…hat answers (#3129)

A Tauri app is two programs in one window: the page calls invoke('save_file')
and a Rust #[tauri::command] answers, and neither names the other. callers
on a command came back empty even when the whole frontend used it, and a
flow stopped at the wire.

A new synthesis pass, tauri-synthesizer.ts, pairs the literals. tauri-command
links the function a call is written in to the Rust function a handler list
registers, with registeredAt at the list. It reads invoke imported, aliased,
through a namespace, dynamically and off the global API; a project's own
functions that hand their first parameter to invoke; and tauri-specta's
commands.fooBar(), which reaches an indexed bindings.ts on its own and is
read by its camelCase name when bindings.ts is not in the index. tauri-event
links an emit to its listeners in either language, and a listener to the
struct deriving tauri-specta's Event.

Registration means a generate_handler! or collect_commands! list in code,
not only one handed straight to tauri::Builder::default(): clash-verge-rev
registers through tauri_specta's builder, and Cmdr's list is built by a macro,
so there the app's declared commands answer. A name a list holds once can be
one function per platform, and all of them link. Apps are scoped by folder,
plugins by name, and a tie links nothing.

Reimplements PR #878 by @vdavid, folding in PR #2524 by @nk33-dev.

Validation: A/B against main on pot-desktop (+37 edges), clash-verge-rev (+93),
Cmdr (+1,318 on a 1,588-file subtree), GitButler (+33), Yaak (+6) and
tauri-specta's examples (+99), none removed, every class triaged. 611 of
Cmdr's 630 commands now have a frontend caller. lightningcss, express and
ripgrep are byte-identical. The pass costs 2 ms on a Rust + JS project with
no Tauri, 153 ms on clash-verge-rev.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@colbymchenry

Copy link
Copy Markdown
Owner

Thanks @nk33-dev, your registration check, call-site edges with registeredAt, shadow handling and sync inputs all carried over into #3129, where they joined #878's typed client and events. We widened registration to tauri-specta's collect_commands! and macro-built lists, since most real apps use those. You're credited in the changelog.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants