Skip to main content

wrdn-effect-promise-exit

Replace React/effect-atom mutation handlers that use promise-mode plus try/catch with promiseExit and explicit Exit handling. Use when lint or review flags try/catch around useAtomSet mutation calls, especially UI handlers that set error/busy state after a failed mutation.

소스 정보

저장소
UsefulSoftwareCo/executor
최근 소스 활동
2026년 5월 5일 23:06
감지된 SKILL.md 언어
영어
스타
4,000
포크
336

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
wrdn-effect-promise-exit
description
Replace React/effect-atom mutation handlers that use promise-mode plus try/catch with promiseExit and explicit Exit handling. Use when lint or review flags try/catch around useAtomSet mutation calls, especially UI handlers that set error/busy state after a failed mutation.
allowed-tools
Read Grep Glob Bash
You fix one pattern: a React handler awaits an effect-atom mutation in `mode: "promise"` and catches failures with `try/catch`. The preferred UI boundary is `mode: "promiseExit"` plus `Exit.isFailure`. This keeps mutation failures as values, matches Effect's error model, and prevents optimistic mutation cleanup from depending on thrown exceptions. ## Trace before changing 1. **Find the mutation setter.** Look for `const doX = useAtomSet(<mutationAtom>, { mode: "promise" })`. 2. **Confirm it is an effect-atom mutation boundary.** The setter should come from `@effect/atom-react` and a mutation atom from `./atoms`, `../api/atoms`, or plugin React atoms. 3. **Find thrown-control handling.** The same handler has `try { await doX(...) } catch (e) { ... }`, usually setting error text, resetting `adding`/`saving`, or showing a toast. 4. **Check for non-mutation async work in the same block.** If the block also awaits follow-up mutations, convert those to `promiseExit` too or keep a narrow boundary only around truly non-effect APIs. 5. **Do not rewrite unrelated local async code.** Probe requests, OAuth popup helpers, `fetch`, and browser APIs may need a different skill unless the lint finding specifically points at the mutation call. ## Fix shape - Change the setter to `{ mode: "promiseExit" }`. - Import `* as Exit from "effect/Exit"` if missing. - Import `* as Option from "effect/Option"` only when extracting an optional error. - Replace `try/catch` around the mutation with: - `const exit = await doX(args);` - `if (Exit.isFailure(exit)) { ...; return; }` - success work after the failure branch. - Use `Exit.findErrorOption(exit)` when preserving an existing error message or typed error branch. - Keep existing typed error handling when present, e.g. `SecretInUseError`, `ConnectionInUseError`. ## Bad ```tsx const doAdd = useAtomSet(addGraphqlSource, { mode: "promise" }); const handleAdd = async () => { setAdding(true); setAddError(null); try { await doAdd({ params: { scopeId }, payload, reactivityKeys: sourceWriteKeys, }); props.onComplete(); } catch (e) { setAddError(e instanceof Error ? e.message : "Failed to add source"); setAdding(false); } }; ``` ## Good ```tsx import * as Exit from "effect/Exit"; import * as Option from "effect/Option"; const doAdd = useAtomSet(addGraphqlSource, { mode: "promiseExit" }); const handleAdd = async () => { setAdding(true); setAddError(null); const exit = await doAdd({ params: { scopeId }, payload, reactivityKeys: sourceWriteKeys, }); if (Exit.isFailure(exit)) { const error = Exit.findErrorOption(exit); setAddError( Option.isSome(error) && error.value instanceof Error ? error.value.message : "Failed to add source", ); setAdding(false); return; } props.onComplete(); }; ``` ## Follow-up mutation chains If success work depends on the mutation result, read it after the failure branch: ```tsx const exit = await doAdd(args); if (Exit.isFailure(exit)) { setAdding(false); return; } const sourceId = exit.value.namespace; ``` If a follow-up effect-atom mutation can fail and the UI treats that as add failure, make that setter `promiseExit` too and branch the same way. Do not put the follow-up mutation in `try/catch` just because the first mutation now returns `Exit`. ## What not to report - `try/catch` around non-effect APIs such as `new URL`, `JSON.parse`, raw `fetch`, or browser popup code. Those may be real lint findings, but they need a different remediation skill. - `useAtomSet(..., { mode: "promise" })` with no local failure handling and no lint finding. Some call sites intentionally let callers decide the boundary. - Tests or SDK/server Effect code. This skill is for React/effect-atom UI mutation handlers. - Manual optimistic placeholder cleanup. Use `wrdn-effect-atom-optimistic` for that; if both patterns appear together, fix optimistic plumbing first, then use `promiseExit` for the remaining mutation boundary. ## Output requirements When reviewing, report: - **File and line** of the `useAtomSet(..., { mode: "promise" })` or `try/catch`. - **Mutation** being called. - **Why** it should return `Exit` at this UI boundary. - **Fix**: the exact setter mode and the failure branch to add. When editing, keep changes local to the handler and imports unless a follow-up mutation in the same success path must also become `promiseExit`.
GitHub에서 보기