- CLAUDE.md: product principles, crate layering, common commands, commits. - .claude/rules: common, Rust, frontend, Tauri IPC, docs and security rules. - .claude/skills: check, add-tauri-command, project-model-change, change-record, msix-integration-test, backlog-status. Refs #16 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2.8 KiB
2.8 KiB
name, description
| name | description |
|---|---|
| add-tauri-command | Installer Studio 데스크톱에 Tauri IPC 명령을 추가하거나 바꾼다. Rust 명령 작성, generate_handler 등록, 자동 생성 권한, capabilities/main.json 허용, TypeScript invoke 타입, README 갱신까지 한 번에 끝낸다. "명령 추가", "IPC", "프런트에서 호출", "capability", "not allowed 오류"에 사용한다. |
Tauri 명령 추가
파일 위치: src/apps/desktop/src-tauri/src/main.rs, src/apps/desktop/src-tauri/capabilities/main.json, src/apps/desktop/src/main.ts.
설계 먼저 결정
- 비즈니스 로직은
package-infra에 함수로 두고 명령은 그 함수를 호출만 한다. CLI(apps/cli/src/main.rs)에서도 같은 함수를 쓸 수 있어야 한다. - 인자로 받을 것은 ID·선택지·사용자 입력값이다. 파일 경로를 프런트엔드에서 받지 않는다. 경로가 필요하면
rfd대화상자 또는 세션 문서에서 얻는다. - 세션을 바꾸는가? →
idle(&session)?를 첫 줄에. - 파일 IO·해시·외부 도구를 실행하는가? →
async fn+spawn_blocking. - 반환 DTO가 새 타입이면
#[derive(serde::Serialize)]+#[serde(rename_all = "camelCase")]. 바이트 수는 문자열.
절차
- Rust 명령
#[tauri::command]
async fn example_action(id: String, session: State<'_, Session>) -> Result<ExampleView, String> {
idle(&session)?; // 세션을 바꾸는 경우만
let doc = document(&session)?;
tauri::async_runtime::spawn_blocking(move || infra::example(&doc, &id).map_err(error))
.await
.map_err(error)?
}
main.rs하단tauri::generate_handler![ ... ]목록에example_action추가.cargo build --locked -p msix-studio --features custom-protocol실행.permissions/autogenerated/example_action.toml이 생긴다. 이 파일은 수정하지 않는다.capabilities/main.json의permissions배열에"allow-example-action"추가(snake → kebab). 기존 순서를 따라 명령 그룹 근처에 넣는다.- TypeScript:
main.ts(또는 담당 모듈)에 반환type선언 후await invoke<ExampleView>('example_action', { id }). 호출은action()분기 안에서busy보호를 받게 한다. - 순수 로직이 생겼으면 별도 모듈로 빼고
tests/<module>.test.mjs에 테스트 추가. src/README.md에서 해당 화면·CLI 절을 갱신한다. 새 오류 코드가 있으면 적는다.check스킬로 전체 검사.
자주 나는 오류
- 런타임
example_action not allowed by ACL: 4단계 누락. permissions/autogenerated에 파일이 없음: 2단계 누락 또는 빌드 미실행.- TS에서
undefined필드: Rustsnake_case↔ TScamelCase불일치.rename_all확인. - 빌드 중 명령이 실행됨: 1단계
idle누락.