Skip to content

Action

Actions are scripts that can be invoked in objects such as flows, processes, and business processes.

The action must meet the following conditions:

  • The input and output parameters are specified.
  • There's the only way to get in

The following is a sample code for a calculator action:

ts
/*
 *Copyright (c) Huawei Technologies Co., Ltd. 2016-2020. All rights reserved.
 *
 * 
 */

import { Decimal } from 'decimal';
import { Error } from 'error';

export class Input {
    @action.param({ type: "String", required: true, description: "the operation type" })
    op: string;

    @action.param({ type: "Number", required: true, description: "the operation value 1" })
    value1: Decimal;

    @action.param({ type: "Number", required: true, description: "the operation value 2" })
    value2: Decimal;
}

export class Output {
    @action.param({ type: "Number", required: true })
    result: Decimal;
}

export class Calculator {
    @action.method({ input: "Input", output: "Output", description: "do a operation" })
    run(input: Input): Output {
        let output = new Output();
        switch (input.op) {
            case "+":
                output.result = this.sum(input.value1, input.value2);
                break;
            case "-":
                output.result = this.sub(input.value1, input.value2);
                break;
            default:
                throw new Error("00001", `unsupported calculator operator ${input.op}`);
        }

        return output;
    }

    sum(a: Decimal, b: Decimal): Decimal {
        return a.Add(b)
    }

    sub(a: Decimal, b: Decimal): Decimal {
        return a.Sub(b)
    }
}

An action can be invoked through a RESTful request. The following parameters are sent for calculation:

bash
{
    "op": "+",
    "value1": 99,
    "value2": 100
}

Entry Method Definition

Use the action.method function to identify the calling method of the action, such as Calculator.run. The entry method has the following requirements:

  • Must be an instance method of a class.
  • There can be only one entry method in an action file.

The action.method function parameter type MethodOptions is defined as follows:

ts
interface MethodOptions {
    //Enter the parameter type name. If no parameter is entered, enter "".
    input: string;

    //Output parameter type name. If there is no output parameter, set this parameter to "".
    output: string;

    //Method label, which is the same as the method name by default.
    label?: string;

    //Method description. The default value is null.
    description?: string;
}

Parameter definition

The identified method can have multiple input and output parameters or none.

All input or input parameters must be encapsulated in a class as an instance member. Each parameter is annotated by action.param.

For example, the instance member of the ActionInput above.

Parameter type ParamOptions of the action.param function is defined as follows:

ts
interface ParamOptions {
    //Parameter type name, which corresponds to the data type supported by the flow.
    type: string;

    //Whether the parameter is mandatory
    required?: boolean;

    //Indicates whether the parameter is a set type.
    isCollection?: boolean;

    //Schema object name. This parameter is valid only when type is set to Object and indicates the schema object bound to the object.
    metaName?: string;

    //Parameter Minimum Value
    min?: number|string;

    //Maximum parameter value
    max?: number|string;

    //Parameter mode
    pattern?: string;

    //Parameter check prompt message
    message?: string;

    //Parameter label, which is the same as the variable name by default.
    label?: string;

    //Parameter description. The default value is null.
    description?: string;
}

Parameter Type

In most cases, actions are provided for flows. Therefore, the input and output parameter types are defined by flows.

  • Boolean

The Boolean type corresponds to the Boolean type of typescript.

ts
@action.param({type: 'Boolean'})
boolVal: boolean;
  • String

The string type corresponds to the string type of typescript.

ts
@action.param({type: 'String'})
stringVal: string;
  • Number

The number type corresponds to the Decimal type of typescript.

ts
import {Decimal} from 'decimal';

@action.param({type: 'Number'})
numberVal: Decimal;

The number type of the typescript cannot be used because the flow does not have the simple number type. The number transferred to the action is a Decimal object, not a simple number.

  • Date

The Date type corresponds to the Date type of typescript.

ts
@action.param({type: 'Date'})
dateVal: Date;

The Date type contains only the year, month, and day, and does not contain the time zone information.

  • Datetime

The Datetime type corresponds to the Date type of the typescript.

ts
@action.param({type: 'Datetime'})
dateVal: Date;

The Datetime type contains the year, month, day, hour, minute, and second.

  • Struct

The Struct type corresponds to the class or interface type of the typescript.

ts
import {Decimal} from 'decimal';

export class Student {
    @action.param({type: 'String'})
    name: string;
    @action.param({type: 'Number'})
    age: Decimal;
}

@action.param({type: 'Student'})
student: Student;

Class members must be decorated with action.param.

  • Object

The object type corresponds to the object type of typescript. You can bind the object to an object by using the metaName attribute.

ts
@action.param({type: 'Object', metaName: 'student__cst'})
objectVal: Object;

After an object is bound, the script engine verifies parameters based on the definition of the object field.

  • Blob

Receives file streams, such as images and audio files. The receiving parameter is fixed to$data

ts
@action.param({ type: "Blob", required: true, description: "file streaming" })
$data: any;
  • File

For receivingmultipart/form-dataFormat data structure, which can be used when the custom API is used to encapsulate the file upload interface.

ts
@action.param({ type: "File", required: true, description: "form data" })
file: http.FormData;
  • Any

The Any type corresponds to the any type of the typescript.

ts
@action.param({type: 'Any'})
anyVal: any;

Defines array parameters.

  • Use [] to represent arrays.
ts
@action.param({type: 'String[]'})
stringList: string[];
  • The isCollection property is used to identify whether the parameter is an array.
ts
@action.param({type: 'String', isCollection: true})
stringList: string[];

isCollection is no longer recommended and is reserved for compatibility.

Parameter Check

required

Defines whether a parameter must have a value.

ts
@action.param({type:'Boolean', required: true})
boolVal: boolean;
@action.param({type:'String', required: false})
stringVal?: string;

The default value of required is false. When required is false, it is recommended that a question mark (?) be appended to the variable definition. Number, tells the typescript compiler that this is an optional member.

min, max

Defines the minimum and maximum values of a parameter.

  • Number type.
ts
import {Decimal} from 'decimal';

@action.param({type:'Number', min: 0, max: 200})
age: Decimal;
  • String type
@action.param({type:'String', min: 0, max: 200, lengthInCharacter: true})
str1: string;

@action.param({type:'String', min: 'zzz', max: 'a'}
str2: string;

When the value of min and max is of the number type, it indicates the length range of a character string. The length is calculated by by byte. You can set lengthInCharacter to true, indicating that the length of a character string is counted by character. If the value of min and max is of the string type, it indicates the range of the string value.

  • Date type.
ts
@action.param({type: 'Date', min: '2018-1-1', max: '2019-12-31'})
dateVal: Date;

Indicates the date range.

  • Datetime type.
ts
@action.param({type: 'Datetime', min: '2018-1-1 00:00:00', max: '2019-12-31 59:59:59'})
dateVal: Date;

Indicates the date and time range.

pattern

  • Date type.

Specifies the default layout of the date parameter. If this parameter is not specified, the built-in layout supported by JavaScript will be used.

ts
@action.param({type:'Date', pattern: 'yyyy-MM-dd'})
dateVal: Date;
  • Datetime type.

Specifies the default layout of the date and time parameters. If this parameter is not specified, the layout supported by the JavaScript built-in will be used.

ts
@action.param({type:'Datetime', pattern: 'yyyy-MM-dd HH:mm:ss'})
dateVal: Date;
  • String type

A regular expression that indicates that a character string complies with a javascript.

Supports the following built-in regular expressions: email, url, postalcode, ip, address, phone

ts
@action.param({type:'String', pattern: 'email'})
email: string;

@action.param({type:'String', pattern: 'url'})
url: string;

@action.param({type:'String', pattern: 'postalcode'})
postalCode: string;

@action.param({type:'String', pattern: 'ip'})
ip: string;

@action.param({type:'String', pattern: 'address'})
address: string;

@action.param({type:'String', pattern: 'phone'})
phone: string;

If it is not a built-in regular expression, you need to write the content of the regular expression:

ts
@action.param({type: 'String', pattern: '^\d{4}-\d{1,2}-\d{1,2}'})
stringVal: string;

message

Define the error prompt message when the parameter value fails to pass the check.

ts
@action.param({type:'String', pattern: 'email', message: '格式不正确的email邮箱'})
email: string;

FAQs

Do not export the class definition by default.

ts
export default class Calculator {

}

After the default keyword is added, the following error message is displayed:

ts
TypeError: Value is not a object: undefined.

The members of the output parameter cannot contain circular references.

ts
export class Input {
    @action.param({type: 'String', required: true})
    name: string;
}

export class Item {
    @action.param({type: 'String'})
    name: string;
    @action.param({type: 'Item'})
    subItems: Item[];
}

export class Output {
    @action.param({type: 'Item'})
    root: Item;
}

export class Action {
    @action.method({input: 'Input', output: 'Output'})
    run(input: Input): Output {
        let item = {
            name: input.name,
            subItems: []
        }

        let out = new Output();

        out.root = item;

        out.root.subItems.push(out.root);
        return out;
    }
}

In the sample code above, out.root.subItems contains out.root itself, forming a circular reference.

An error is reported in the following scenarios:

  • Return to flow, front end, etc.
  • Used as the console.log parameter.
  • Other scenarios involving object serialization, such as JSON.stringify

This is because most serialization libraries do not support circular-referenced structures.