Action Engine
What is Action Engine?
Action Engine is shared infrastructure for executing business actions through a typed contract.
DYONA defines WHAT action to execute and WITH WHAT context.
The consuming application decides HOW to execute it.
Action Engine does not know about fetch or Axios, URLs, endpoints, JWT or authentication, a backend, or business rules. Those decisions remain in the consuming application.
DyonaAction
type DyonaAction = {
id: string;
label: string;
icon?: string;
scope: 'global' | 'record';
requiresParameters?: boolean;
};
globalruns without requiring a selected record.recordruns against one record and requirescontext.record.requiresParametersindicates that an object of parameters must be supplied before execution. This is developed further in Action Dialog.
DyonaActionContext
type DyonaActionContext = {
sourceId?: string;
record?: Record<string, unknown>;
values?: Record<string, unknown>;
parameters?: Record<string, unknown>;
};
The context carries the information the application needs to perform an action. A record action requires context.record; sourceId, values, and parameters are optional context supplied by the caller.
Execute an action
This complete example uses an Approve order record action. The executor simulates application logic only: it does not invent a backend or endpoint.
import {
executeDyonaAction,
type DyonaActionExecutor,
} from '@typhonsoftware/dyona-form';
const action = {
id: 'approve-order',
label: 'Approve order',
scope: 'record',
} as const;
const context = {
sourceId: 'orders',
record: {id: 1024, status: 'pending'},
};
const executor: DyonaActionExecutor = async ({context}) => {
// Application business logic belongs here.
return {
success: true,
message: 'Order approved',
data: {
id: context.record?.id,
},
};
};
const result = await executeDyonaAction(action, context, executor);
Execution flow
DyonaAction
+
DyonaActionContext
↓
executeDyonaAction()
↓
DyonaActionExecutor
↓
DyonaActionResult
Global actions
A global action has the same contract but does not require a record.
const globalAction = {
id: 'generate-order-summary',
label: 'Generate order summary',
scope: 'global',
} as const;
const globalExecutor: DyonaActionExecutor = async () => ({
success: true,
message: 'Order summary generated',
data: {totalOrders: 42},
});
await executeDyonaAction(
globalAction,
{sourceId: 'orders'},
globalExecutor,
);
DyonaActionResult
At an introductory level, an action result can include:
success: whether the action succeeded.message: a result message for the application to present.fieldErrors: backend field messages keyed by form field name.data: application-specific returned data.refresh: targets that may need to refresh.
refresh and fieldErrors are covered in more detail in Action Result + Refresh. When this result is returned by DyonaForm's onSubmit or custom onAction, DyonaForm also presents the corresponding success, general-error, and field-error feedback.
Why this matters
Current and future DYONA components can reuse the same action contract without coupling themselves to a backend. Each consuming application retains its own transport, authentication, and business logic while sharing a consistent execution boundary.
Continue learning
- Data Sources — another shared infrastructure contract.
- Try Actions in the Lab →