Logic: Actions (RPC)
Logic: Actions (RPC)
Actions (Remote Procedure Calls) allow you to define custom backend functions that go beyond simple CRUD. They are integrated into the metadata, meaning the Frontend knows exactly how to render them (buttons, confirmation dialogs, forms) and the Backend knows how to validate them.
1. What is an Action?
Unlike a Hook (which reacts to CRUD events), an Action is explicitly invoked by a user or a system.
| Feature | Action | Hook |
|---|---|---|
| Trigger | Explicit (Button, API Call) | Implicit (Database Event) |
| Input | Custom Arguments (params) | Database Record |
| Output | Custom Result (JSON) | None (Void) |
| Use Case | "Approve Invoice", "Sync LDAP" | "Validation", "Audit Log" |
2. Defining Actions
Actions require two parts:
- Declaration: in
*.object.yml(Defines the "Interface" & "UI"). - Implementation: in
*.action.ts(Defines the "Logic").
Step 1: Declare in YAML
Define the action's signature in the Object file.
Step 2: Implement in TypeScript
Create a corresponding .action.ts file in the same directory.
Use the ActionDefinition type for full type safety.
3. Action Context (ctx)
The handler function receives a single context object with the following properties:
| Property | Type | Description |
|---|---|---|
objectName | string | The API name of the object (e.g., invoice). |
actionName | string | The API name of the action (e.g., mark_paid). |
id | string | number | (Record Actions only) The ID of the target record. |
input | T | The validated arguments passed by the caller. |
api | HookAPI | Database API (find, create, update, delete, count). |
user | object | The current session user (contains id, name, etc.). |
4. Parameter Types
The params section in YAML supports the same types as Object Fields. This allows the Frontend to auto-generate beautiful forms.
text,textarea,number,boolean,date,datetimeselect(Dropdown)lookup(Reference to another object)file(Attachment)
Example: Lookup Parameter
5. Invoking Actions
A. Via Server-Side Code (app.executeAction)
You can call actions from other parts of your backend (e.g., Cron jobs, Webhooks).
B. Via HTTP API (RPC)
ObjectQL Server uses a unified RPC endpoint (typically mounted at /api/objectql).
Note on Versioning: It is recommended to mount the ObjectQL handler under a versioned prefix like
/api/v1/objectqlin your Express/Node app to manage future breaking changes.
C. Via Frontend SDK
6. Transaction Safety
By default, Actions are NOT automatically wrapped in a database transaction. If you need atomicity (all-or-nothing), you should manage it manually, or if using a driver that supports it, rely on the api methods which might share a transaction context if configured (though HookAPI is currently stateless).
Future versions of ObjectQL may introduce transactional decorators.
7. Best Practices
- Thin Controllers: Keep your
.action.tshandlers relatively thin. If the logic is complex, move it to a dedicated Service class. - Input Validation: Although ObjectQL checks types defined in YAML, always validate business rules (e.g., "Amount must be positive") inside the handler.
- Return JSON: Always return a JSON serializable object. Do not return database cursors or complex class instances.