Handlers
Build local handlers that run actions in the current process.
A local handler runs actions in the current process. Build one, register it on the runtime, and it answers incoming requests. There are three ways to build one — pick whichever reads best.
Map syntax (preferred)
Section titled “Map syntax (preferred)”import { createLocalHandler } from "@nice-code/action";
const userHandler = createLocalHandler().forDomainActionCases(userDomain, { getUser: async (action) => { const user = await db.users.find(action.input.userId); if (!user) throw err_user.fromId("not_found", { userId: action.input.userId }); return user; }, updateName: async (action) => { await db.users.update(action.input.userId, { name: action.input.name }); return { success: true }; },});Each handler receives the full action — action.input is typed, and action.context carries routing info like originClient (see Bi-directional).
One action at a time
Section titled “One action at a time”const userHandler = createLocalHandler() .forAction(userDomain.action.getUser, async ({ input }) => db.users.find(input.userId));Wrap an object off the domain
Section titled “Wrap an object off the domain”const userHandler = userDomain.wrapAsLocalHandler({ getUser: async ({ userId }) => { /* ... */ }, updateName: async ({ userId, name }) => { /* ... */ },});Here each handler receives the destructured input directly rather than the action wrapper — the most concise form when you don’t need action.context.
Partial handlers
Section titled “Partial handlers”wrapAsPartialLocalHandler is the same as wrapAsLocalHandler but lets you implement only some of a domain’s actions — useful for local-first clients that resolve a few actions themselves and forward the rest.
const partial = userDomain.wrapAsPartialLocalHandler({ getUser: async ({ userId }) => cache.get(userId), // others forwarded over the carrier});Once built, handlers are passed to serveChannel (acceptor) or registered for toConnector pushes via connectChannel’s onPush (connector).
Next: Serving & connecting →