createActions
createActions<
TUser,TServices>(config):object
Defined in: packages/actions/src/create-actions.ts:132
Creates a scoped action factory bound to a shared context provider.
Returns two functions — createAction and composeActions — that share the
same getContext callback. This ensures every action in the application resolves
its database, user, and grants consistently.
Services registered via the optional services config are injected into
every action’s context as ctx.services, so handlers can access shared
dependencies (HTTP clients, mailers, third-party APIs) without importing
module-level singletons. Services are always defined on ctx.services
— the factory fills in {} when no services are configured so handlers
can destructure safely.
Type Parameters
Section titled “Type Parameters”TUser = any
The shape of the authenticated user object.
TServices
Section titled “TServices”TServices extends ActionServices = ActionServices
The shape of the registered services map.
Parameters
Section titled “Parameters”config
Section titled “config”ActionsConfig<TUser, TServices>
The ActionsConfig providing the getContext callback
and optional services bag.
Returns
Section titled “Returns”An object with createAction and composeActions functions.
composeActions()
Section titled “composeActions()”composeActions: <
TActions>(actions) =>ComposedActions<TActions>
Combines multiple action definitions into a single
route handler that dispatches by the _action discriminator field.
The returned ComposedActions object provides a unified .action handler,
a .loader() wrapper that checks permissions for all actions at once,
and a .client descriptor covering every action name.
Type Parameters
Section titled “Type Parameters”TActions
Section titled “TActions”TActions extends Record<string, ActionDefinition<any, any, any>>
A record mapping action names to their definitions.
Parameters
Section titled “Parameters”actions
Section titled “actions”TActions
An object of named action definitions to compose.
Returns
Section titled “Returns”ComposedActions<TActions>
A ComposedActions object with combined handler, loader, and client descriptor.
Example
Section titled “Example”const composed = composeActions({ deletePost, publishPost, unpublishPost,});
export const action = composed.action;export const loader = composed.loader(async ({ request, params }) => { return { post: await getPost(params.slug) };});createAction()
Section titled “createAction()”createAction: <
TInput,TResult>(config) =>ActionDefinition<TInput,TResult,TUser>
Defines a single permission-aware action.
Takes an OperationsFn that builds a database Operation from
the parsed input and action context. Returns an ActionDefinition
with .action, .loader(), .client, and .buildOperation facets.
Type Parameters
Section titled “Type Parameters”TInput
Section titled “TInput”TInput
The expected input shape for this action.
TResult
Section titled “TResult”TResult
The return type of the action handler.
Parameters
Section titled “Parameters”config
Section titled “config”OperationsFn<TInput, TResult, TUser> |
{ handler: OperationsFn<TInput, TResult, TUser>; input?: InputParser<TInput>; }
handler
Section titled “handler”OperationsFn<TInput, TResult, TUser>
The operation builder. Same shape as the legacy positional form.
input?
Section titled “input?”InputParser<TInput>
Optional typed input parser, e.g. produced by defineInput({ ... }).
When set, the parser runs over the request’s raw input before the
handler is invoked. Validation failures throw InvalidInputError
with field-keyed messages — the call this fix exists for is
Number(formData.get("position")) silently producing NaN, which
z.number() / z.integer() rejects upfront.
Returns
Section titled “Returns”ActionDefinition<TInput, TResult, TUser>
An ActionDefinition with action handler, loader wrapper, client descriptor, and build method.
Example
Section titled “Example”const deletePost = createAction<{ postId: string }, Response>( (db, input, ctx) => compose( [db.delete(posts).where(eq(posts.id, input.postId))], async (runDelete) => { await runDelete({}); return redirect("/"); }, ),);
export const action = deletePost.action;Examples
Section titled “Examples”import { createActions } from "@cfast/actions";
export const { createAction, composeActions } = createActions({ getContext: async ({ request }) => { const ctx = await requireAuthContext(request); const db = createCfDb(env.DB, ctx); return { db, user: ctx.user, grants: ctx.grants }; },});type Services = { nutritionApi: NutritionApi };
export const { createAction } = createActions<AppUser, Services>({ getContext: async ({ request }) => { ... }, services: { nutritionApi: createNutritionApi(env.NUTRITION_API_KEY) },});
const lookupFood = createAction((db, input, ctx) => ({ permissions: [], run: async () => ctx.services.nutritionApi.lookup(input.name),}));