Action Result + Refresh
Every DYONA action returns the same public result contract:
type DyonaActionRefreshTarget = {
sourceId: string;
};
type DyonaActionResult<TData = unknown> = {
success: boolean;
message?: string;
fieldErrors?: Record<string, string>;
data?: TData;
refresh?: DyonaActionRefreshTarget[];
};
Result properties
-
successis required. It is a boolean that indicates the logical result of the action. -
messageis optional. It is a string that the consuming UI can use. -
datais optional and generic. DYONA does not impose its structure. For example:data: {id: 1024,status: 'rejected',} -
refreshis optional and declarative. For example:refresh: [{sourceId: 'orders'},{sourceId: 'dashboard'},]It means: “These logical sources may have become stale.” It does not mean that Action Engine reloads them automatically.
Action Feedback in DyonaForm
When onSubmit or a custom onAction returns a DyonaActionResult, DyonaForm presents the result without requiring a manual Alert.
Success
{success: true, message: 'Record saved successfully.'}
Shows success feedback that closes automatically. Without message, DYONA uses its localized generic success message.
General error
{success: false, message: 'The operation could not be completed.'}
Shows persistent error feedback that the user may close manually.
Field error
{
success: false,
message: 'The record could not be saved.',
fieldErrors: {name: 'This name already exists.'},
}
fieldErrors are applied to the existing field validation and error summary. They remain visible while the user edits and are cleared when a new valid submit or custom action begins. A handler returning void keeps the previous behavior; a thrown technical error is not converted into success: false.
Architecture
Action executor
↓
DyonaActionResult
↓
refresh: [{sourceId: 'orders'}]
↓
Consumer / future orchestrator
decides how to react
Action Engine validates refresh, transports it, and returns the same result produced by the executor.
Action Engine does not:
- execute a refresh;
- call
executeDyonaDataSource; - know
DyonaGridorDyonaScreen; - search for mounted components;
- use Redux, an Event Bus, or Context to refresh;
- deduplicate targets.
Runtime rules
refreshis optional.- When present, it must be a non-empty array.
- Each item must be an object.
sourceIdmust be a non-empty string.- Validation uses the value after
trim. - The engine does not modify or normalize
sourceId. - Repeated targets are allowed.
refreshmay also be present whensuccess: false.context.sourceIddoes not automatically become a refresh target.
Successful result
const executor: DyonaActionExecutor = async () => ({
success: true,
message: 'Order rejected',
data: {
id: 1024,
status: 'rejected',
},
refresh: [
{sourceId: 'orders'},
],
});
A failed result can still refresh
This is also valid:
{
success: false,
message: 'The operation was only partially completed',
refresh: [
{sourceId: 'orders'},
],
}
An operation can partially fail while still changing data, so a consumer may need to react to its refresh targets.
Relation to Action Dialog
DyonaActionDialog does not process refresh. It passes the complete DyonaActionResult to onResult(result) without removing message, fieldErrors, data, or refresh.
The current Action Dialog Lab example already demonstrates this with refresh: [{sourceId: 'orders'}].
Continue with Action Engine or Action Dialog.