Automation scripts
An automation is a piece of JavaScript code that implements some business logic and conforms to this interface:
export interface Script {
label?: string;
description?: string;
security?: {
runAs?: string;
deny: string[];
allow: string[];
}|string;
triggers: Trigger[];
exec?: ScriptFn;
}
One automation script per file. |
export default {
label: "label goes here",
description: "description goes here",
// Use the ones you need, delete the rest
triggers ({ before, after, on, at }) {
return before('event goes here')
.where('constraint goes here')
// Add/remove constraints here
},
// remove async if you aren't doing any async operations
// use object destructuring for args and ctx
async exec(args, ctx) {
// Code goes here
},
}
See server script samples, and client script samples for more. |
There are two main categories of automation scripts; server scripts and client scripts.
Server scripts |
These are executed in the Corteza Corredor server. Use server scripts when:
Example use cases:
|
Client scripts |
These are executed in the client’s browser (user agent, if you will). Use client scripts when:
Example use cases:
|
A rule of thumb — if we need to interact with the user (show notification, request confirmations), use client scripts. Else, use server scripts.
Treat client scripts as less secure (you can freely inspect their contents from the browser) and less reliable (a user can manually terminate their execution — closes the page). |
Script execution
The execution function (exec
) implements the business logic that the automation script should perform.
Any code that you want to execute should be directly in the execution function or referenced via importing.
interface ScriptFn {
(args: exec.Args, ctx?: exec.Ctx): unknown;
}
Execution arguments
The arguments (args
) differ based on the event that triggered the automation script.
Refer to resources and events for a complete list.
Arguments to a client-script are provided via references to the original objects, meaning that any change to the argument parameter will reflect to the original object.
Arguments to a server-script are provided as a copy of the original object, meaning that the changes will not be reflected on the original object.
Execution context
The context (ctx
) is static for all events.
ctx.console
-
console
provides a logger. Client scripts refer to thewindow.console
objects; server scripts refer to aPino
instance. ctx.log
-
Shortcut for
ctx.console.log
. ctx.$authUser
-
Auth user is a reference to the invoking user.
ctx.SystemAPI
-
API client for Corteza System interaction.
ctx.ComposeAPI
-
API client for Corteza Low Code interaction.
ctx.MessagingAPI
-
API client for Corteza Messaging interaction.
ctx.System
-
Corredor helper for the Corteza System.
ctx.Compose
-
Corredor helper for the Corteza Low Code.
ctx.ComposeUI
-
Corredor helper for the Corteza Low Code user interface.
ctx.Messaging
-
Corredor helper for the Corteza Messaging.
ctx.frontendBaseURL
-
Base URL used by front-end web applications. This is useful when generating URL’s that point to the Corteza applications.
Execution result
The execution result determines what should happen next.
- Unknown Error
-
Any unknown error (other than
Aborted
) terminates the current script execution and prevents the event from triggering any additional automation scripts. - Aborted Error
-
An error with the value of
'Aborted'
stops the execution of the current automation script. The event is able to trigger any additional automation scripts. false
-
Same as Aborted Error.
- unknown
-
Any other result indicates that the execution was successful and the next script can be triggered. What should happen next is relative to the automation script; see below sections for more details.
|
Implicit script execution result
The following only applies for before events. |
When a value is returned, that value is used instead of the original value.
export default {
// Use the ones you need, delete the rest
triggers ({ before }) {
return before('create', 'update')
.where('module','contact')
},
exec({ $record }, ctx) {
$record.values.FullName = `${$record.values.FirstName} ${$record.values.LastName}`
return $record
},
}
The above example calculates the FullName
property from the FirstName
and LastName
.
The return $record
instructs that the new version of the $record
should be used (the one with the FullName
calculated).
If we didn’t return anything (null
or undefined
for example) the change would be reverted.
The return value for after events is discarded (can not be updated). |
Sink script execution result
When a value is returned, that value is used as an HTTP response.
export default {
security: 'super-secret-user',
triggers ({ on }) {
return on('request')
.where('request.path', '/some/extension')
.where('request.method', 'GET')
.for('system:sink')
},
exec ({ $request, $response }, { Compose }) {
$response.status = 200
$response.header = { 'Content-Type': ['text/html; charset=UTF-8'] }
$response.body = `<h1>Hello World!</h1>`
return $response
},
}
The above example returns a simple static HTML document with a Hello World!
written over it.
You can use this to implement the OAuth protocol or a confirmation page.
This isn’t limited to simple HTML documents.
Just make sure that your responses are properly structured (content type, status, and body). |
export default {
security: 'super-secret-user',
triggers ({ on }) {
return on('request')
.where('request.path', '/model/roi')
.where('request.method', 'GET')
.for('system:sink')
},
async exec ({ $request, $response }, { Compose }) {
$response.status = 200
$response.header = { 'Content-Type': ['application/json'] }
let pl = {}
try {
pl.product = await fetchProduct($request.query.productCode[0])
pl.roi = await calculateRoi(pl.product)
} catch ({ message }) {
$response.status = 500
$response.body = JSON.stringify({
error: message,
})
return $response
}
$response.body = JSON.stringify(pl)
return $response
},
}
DevNote include other trigger types. |