The public.actions
table contains the actions code for server-side functions that operate within a single transaction. Actions have access to the FunDB API, and they are restricted to the role of the user who invoked the action.
An action is an ECMAScript module that exports a handler function by default. The signature of the action functions and the API available internally can be examined here in the form of TypeScript signatures
https://bitbucket.org/ozma/ozma-api/src/master/src/serverside_api.d.ts
Column | Description |
---|---|
schema_id |
Name of the schema (identifier) containing the action. |
name |
Name of the action. |
function |
JavaScript code of the action. |
An action can take arguments that are passed to FunDB during the action call. Action returns data that will be passed back to the client:
return { ok: true }
return { ref: { "schema": "foo", "name": "bar" }, target: "modal" }}
return { action: { "schema": "foo", "name": "bar" }, args: { "arg1": value } }
The example below shows code snippets of a single procedure that uses different FunDB API calls.
This action:
FunDB.getUserView()
call (lines 9-12)export default async function handleEvent(args) {
const accountId = args.id;
const queryStr = `{ $account reference(fin.accounts) }:
SELECT id, amount, account
FROM fin.transactions
WHERE account = $account`;
const exprResult = await FunDB.getUserView(
{ type: "anonymous", query: queryStr },
{ account: accountId }
);
var result = [];
for (var row of exprResult.result.rows) {
var resultRow = {};
for (let i = 0; i < row.values.length; i++) {
var fieldName = exprResult.info.columns[i].name;
var fieldValue = row.values[i].value;
resultRow[fieldName] = fieldValue;
}
result.push(resultRow);
}
/* ... */
FunDB.insertEntity()
call (lines 5-10) /* ... */
const dateTime = new Date();
const fixAmountId = await FunDB.insertEntity(
{ schema: 'fin', name: 'fix_amount'},
{
account: accountId,
created_datetime: dateTime
}
);
/* ... */
FunDB.updateEntity()
call (lines 8-12) /* ... */
let amount = 0;
for (const transaction of result) {
amount += transaction.amount;
}
await FunDB.updateEntity(
{ schema: 'fin', name: 'fix_amount'},
fixAmountId,
{ amount: amount }
);
/* ... */
FunDB.deleteEntity()
call (lines 4-7) /* ... */
for (const transaction of result) {
await FunDB.deleteEntity(
{ schema: 'fin', name: 'transactions'},
transaction.id
);
}
return { ok: true }
A procedure call can be initiated from ozma.io interface (FunApp) by clicking a button or by calling from another action.
If you want to add a button that calls an action, you need to add an object describing the button in the @buttons
attribute of the user view:
action: { schema: 'action_schema', name: 'action_name' }
- link to action that will be called by clicking the buttonargs: { arg1: 'value1', arg2: value2 }
- arbitrary data that will be passed to the actiondisplay
, icon
, variant
, caption
- additional buttons attributes. (More info about buttons is here).SELECT
/*...*/
@buttons = [
{
display: 'desktop',
icon: 'playlist_add',
variant: 'success',
caption: 'Fix Amount',
action: {
schema: 'fin',
name: 'fix_amount_for_contact'
},
args: {
id: $id
},
}],
The procedure code will be executed by clicking on the button.
Ozma will return an OK (200) status
if action code will be executed successfully.
If an error will be occured during the procedure execution, a message will appear in the interface and in the browser console, all changes initiated by the action will be rolled back to the initial state.
The procedure can initiate the call of another action (or the same one, but, for example, with different arguments).
export default async function handleEvent(args) {
/* ... */
return {
action: {
"schema": "action_schema",
"name": "action_name"
},
args: {
"arg1": value,
}
}
}
In this case, a call to another action will be initiated in another transaction after the successful exeution of the current action.
If you call a function from itself, you need to avoid an infinite loop (you should add a condition under which the action will return a default response { ok: true }
).