ServerDynamic Objects
Hooks & Flows
Pre-flows, post-hooks, relationship hooks, and automation for Dynamic Objects.
Pre-Flows (Automation)
Before a record is written, OperationHandlerService checks for active Flow definitions with PRE_CREATE or PRE_UPDATE triggers:
Use Cases
- Field defaulting based on other fields
- Complex validation logic
- Data normalization
Execution
Pre-flows run in-process using the internal Flow Engine:
const preFlows = await FlowIntegrationService.runPreFlows({
entity,
operation: "CREATE",
data,
context,
});Post-Hooks
After successful database operations, standard crudHooks are checked. For Dynamic Objects, hooks are resolved by entity name:
dynamicHooks.register({
entityMatcher: "Invoice",
opMatcher: "create",
stage: "afterSuccess",
handler: async ({ result, context }) => {
// Notify external systems
// Update related records
// Trigger webhooks
},
});Relationship Hooks
When a LOOKUP field is populated, the system checks for cascade behaviors defined in metadata:
Cascade Options
| Behavior | Description |
|---|---|
CASCADE | Delete related records when parent deleted |
RESTRICT | Prevent parent deletion if related records exist |
SET_NULL | Set lookup to NULL on parent delete |
NONE | No referential action |
These are implemented as before hooks that verify foreign key existence.
Hook Context
interface DynamicHookContext {
entity: string;
operation: "CREATE" | "UPDATE" | "DELETE";
params: unknown;
result?: unknown;
context: {
org: string;
user: User;
session: Session;
};
}Registration
Hooks are registered in hooks.ts or via the factory:
import { registerDynamicHook } from "./factory";
registerDynamicHook(
{ entity: "Invoice", op: "create" },
{
before: async (ctx) => {
// Validate or transform params
return ctx.params;
},
after: async (ctx) => {
// Side effects
},
}
);