Automation nodes
The triggers and actions the DMS registers in the procedure builder of the automation module, their inputs, test runs, and the $ keys their texts use.
When @antelopejs/dms-automation is loaded, the DMS registers its own nodes in the procedure builder. It adds triggers for its events (dms.member-added, dms.member-removed, dms.invite-created, dms.user-registered, dms.record-created, dms.record-updated, dms.record-deleted) and the actions below. Every input of an action is a port. Set it in the inspector, or wire it from a trigger's output or a data node.
dms.send-notification
Sends an in-app notification under the AutomationSubject, built as the Notification() builder builds it.
| Input | Type | Notes |
|---|---|---|
title | string, required | Literal text, or a $ translation key resolved in each recipient's language |
description | string | Same as title. Empty by default |
params | object | Interpolation params of both texts. Strings and numbers are kept, booleans read as their text, and nested values are dropped with a warning |
tone | neutral primary success warning error | Icon well colour. Unset reads primary while unread |
icon, linkTo | string | i-ph-bell by default, and the page the notification opens |
userId | string | One recipient, such as a trigger's userId |
userIds | string | Recipients, combined with userId |
roleIds | string | Every member holding one of the roles |
tenantId | string | Restricts roleIds to that tenant's members (toRoles(roleIds, { tenantId })). Empty means the default tenant |
idempotencyKey | string | Stable event key, such as a trigger's deliveryId. A replay of the same event reaches each recipient once |
At least one of userId, userIds or roleIds is required. Otherwise the run fails with dms.send-notification requires at least one of userId / userIds / roleIds.
A procedure that welcomes each new member, with its texts in the project's locales, wires a Member added trigger (dms.member-added) to a Send notification node set as follows:
| Port | Value |
|---|---|
userId | wired from the trigger's userId |
title | $my_app.automation.welcome.title |
description | $my_app.automation.welcome.body |
params | { "team": "Support" }, set in the inspector or wired from a node that outputs an object |
tone | success |
linkTo | /getting-started |
idempotencyKey | wired from the trigger's deliveryId |
The keys live in the project's locale files like any other (Localization):
{
"my_app": {
"automation": {
"welcome": {
"title": "Welcome aboard",
"body": "The {team} team is here to help."
}
}
}
}
A notification node set up with a literal title and description, before these inputs existed, keeps working unchanged.
dms.send-email
Sends an email through the project's interface-email provider (Email templates and rendering).
| Input | Type | Notes |
|---|---|---|
to | string, required | Recipient address |
subject | string, required | Subject line, sent as given |
html | string | The body, written out |
template | string | Name of a template registered with RegisterHtmlTemplate, rendered instead of html |
props | object | Props the template is rendered with |
language | string | Language the template is rendered in. The recipient's own when the address belongs to a user |
One of html or template is required. A template that no module registered fails the run instead of sending an empty email. The output holds success, and messageId or error.
dms.invite-user
Invites an address to a tenant, as the members page does. An existing user becomes a member directly. Anyone else receives an invitation, and its email unless sendEmail is false. An address that is already a member is left unchanged.
| Input | Type | Notes |
|---|---|---|
email | string, required | Address to invite |
tenantId | string | Tenant to invite into. See the tenantId input |
roleIds | string | Roles of the new member |
asTenantOwner | boolean | false by default |
sendEmail | boolean | true by default |
language | string | Language of the invitation email and of the account it leads to. en when empty |
firstname, lastname | string | The invitee's names, stored with the invitation and used in its greeting |
inviterName | string | Who the invitation email says it comes from |
The output kind is added, invited or already-member, with the userId or the inviteId.
The tenantId input
An action has no tenant of its own. The execution context carries none, whoever fires the procedure. A node that acts on tenant data therefore takes a tenantId input, which a procedure wires from its trigger. The member, invite and registration triggers output the tenantId of their event.
Left empty, a tenant-scoped node acts on the default tenant (DEFAULT_TENANT_ID, "default", from @antelopejs/interface-dms/constants). A single-tenant project has only that tenant. dms.invite-user invites there, and dms.send-notification matches its roleIds there. In a multi-tenant project, wire the trigger's tenantId into every node that takes one.
Test runs
The three actions declare dryRun. A Test run in the builder checks their input as a real run would, then sends and creates nothing.
| Action | In a test run | Output |
|---|---|---|
dms.send-email | Refuses a missing body or an unregistered template. Renders and sends nothing | { success: true } |
dms.send-notification | Refuses a missing recipient, an unknown tone or bad params. Notifies nobody | { ok: true } |
dms.invite-user | Looks the address up in the tenant. Creates no user, member or invite, and sends no email | already-member or added with the user's id, else invited with no inviteId |
Texts in the builder
The builder shows a node's name and description, and each schema property's title and description, through processI18n. Each one can be a $ key instead of literal text. The DMS nodes carry keys only, under dms.automation.* of the dms-core locales (en and fr):
triggers.<trigger>andactions.<action>hold a node's name, its description, and its per-node field descriptions.fields.<property>holds the field labels that its nodes share.
A module that registers nodes of its own does the same under its namespace:
export const myAction: ActionType = {
id: "my_app.archive",
name: "$my_app.automation.archive.name",
description: "$my_app.automation.archive.description",
inputSchema: {
type: "object",
properties: {
reason: { type: "string", title: "$my_app.automation.fields.reason" },
},
},
// ...
};
The builder names an untitled property by its key in words. The canvas labels a port by its key, whatever its title.