This example shows the intended ergonomic direction for Mutaflow using real files in this folder.
- src/createTodoFlow.ts: flow definition using
createServerActionAdapter(...) - src/createTodoSafeActionFlow.ts: flow definition using
createNextSafeActionFlow(...) - src/testCreateTodoSafeFlow.ts: small
@mutaflow/testkitexample for flow assertions - src/store.ts: optimistic resource registry and mutation event stores
- src/CreateTodoButton.tsx: client-side trigger with
useFlow,useResource,useFlowState, anduseMutationEvents - src/MutationDebugPanel.tsx: richer devtools panel with grouping, filters, summary, and inspector
- src/App.tsx: tiny app shell
- a
createFlow(...)definition around a Next-oriented action adapter createServerActionAdapter(...)for wrapping plain server actionscreateNextSafeActionFlow(...)for a shorternext-safe-actionsetup@mutaflow/testkitfor flow assertions and event/resource checks- flow
meta,middleware,beforeRun,afterSuccess,afterError, andonSettled consistency.immediate(...)andconsistency.staleWhileRevalidate(...)createResourceStore(...)with a realtodos:listtargetcreateMutationEventStore(...)as the base for future devtoolsoptimistic.insert(...)for list-first optimistic behaviorreconcile.onSuccess(...)replacing the optimistic resource after successuseResource(...)for reading resource state from the store in ReactuseFlow(...)for pending state, retries, cancellation, and mutation executionuseFlowState(...)for reading the latest flow stage from the event streamuseMutationEvents(...)for observing the mutation timeline in React@mutaflow/devtoolssummary, grouped timeline, filters, and event inspector- reusable invalidation registries via
createInvalidationRegistry(...),defineTags(...), anddefinePaths(...)
If you already use next-safe-action, the helper layer removes one wrapper level:
import { optimistic } from "mutaflow";
import { createNextSafeActionFlow } from "mutaflow/next-safe-action";
const createTodoFlow = createNextSafeActionFlow({
action: createTodoAction,
optimistic: optimistic.insert({
target: "todos:list",
item: (input) => ({ id: `temp:${input.title}`, title: input.title, pending: true }),
}),
});The test example in src/testCreateTodoSafeFlow.ts shows the intended shape for testing optimistic flows:
import { createTestStore, expectEvents, expectReconciled, runFlowAndCollectEvents } from "@mutaflow/testkit";This example is intentionally small and framework-light. It exists to document the desired API direction, not to be a full runnable app yet.