Overview
This how-to guide details how to create a custom (Bring Your Own) Average and Rounding Operation. It demonstrates how to build an asset that fully integrates with the Unqork platform.
The Unqork platform has built-in support for average and rounding, so you don't need to create a custom operation for them. Use this guide as an example for the operation implementation process.
The Bring Your Own feature is intended for developers who have a strong understanding of the Unqork Designer Platform and JavaScript.
BYO Average and Round Operation Ideation
For this example, the fictional client company "ABC" wants to implement an operation for averaging a value and rounding it to a specified decimal value. The operation itself should let Creators configure array values for rounding and specify the number of values. The client requests the operation to support an event that emits when a user clicks on an item in the checklist. They also ask that it include an operation that sets the completed (checked/unchecked) state of a single item in the checklist.
As the developer assigned to this task, break down and document the client's ask into actionable sections:
Asset Types: What’s needed to meet the client's requirements of an averaging and rounding asset?
Component(s): Does the client's request require the creation of something not currently supported in the Unqork platform?
Event(s): Does the asset need to emit an event when it's used? What action should emit the event?
Operation(s): Does the asset need to be manipulated by other elements using an operation?
Inputs & Outputs: Catalog a list of potential inputs and outputs for the asset. Events are typically an output in this list.
Naming Scheme: Develop a naming scheme for the asset that aligns with Unqork values and avoids conflicts with potential future custom assets.
To understand naming scheme limitations, view the Important callout in the overview of our Bring Your Own (BYO): Understanding the manifest.json File article.
Now that the client has described the ask, create a document detailing all the potential elements the operation asset requires.
Example Ideation Documentation
The sections below detail the product requirements that meet the client's request. Developers use this information to implement the operation’s JavaScript, create the manifest file and package, then package it to the Unqork Designer Platform.
Operation
An operation that averages an array of numbers and rounds the result to a specified number of decimals.
Operation Name | Operation Value | Description | ||
---|---|---|---|---|
Average and Round |
| Input options: these are the fields Creators use to average numbers and specify the decimal rounding value. | ||
↳ |
| An array of numbers to average. By default, the value is | ||
| An integer representing the number of decimal places for rounding. Constrained: A value between Placeholder: Specify an integer between By default, the value is | |||
Context Payload. This is the operation’s output after processing the input values. | ||||
↳ |
| The averaged value after rounding to the requested decimals. This value is returned in the operation's context. |
Inputs
Creators use the input fields to average a set of numbers and specify the decimal rounding value.
Parameter | Object Type | Description |
---|---|---|
| number array | An array of numbers to average. By default, the value is |
| integer | An integer representing the number of decimal places for rounding. Constrained: A value between Placeholder: Specify an integer between By default, the value is |
Outputs
This is the output the operation produces after processing the input values.
Parameter | Description | |
---|---|---|
| A schema that defines the output of the operation. It tells the Unqork platform what data to expect back so it can be used in subsequent steps of a workflow. | |
↳ |
| Return an object with a single property named result, which is a number. |
Naming Scheme
Verify that all naming values do not conflict with existing Unqork assets or other custom assets in the environment.
IMPORTANT
Unqork does not enforce programmatic name spacing for custom asset types. All type values for components, operations, and events must be globally unique. If multiple custom assets share the same type, or if a custom asset uses a type that conflicts with a native Unqork type, the runtime will render or execute only the first matching definition. Doing so leads to unpredictable behavior, asset shadowing, or broken functionality—especially when bundling or importing multiple packages.
It is the responsibility of the developer to ensure type uniqueness to prevent collisions. Component, operation, and event types require a unique name to avoid collision issues.
To avoid namespace issues, prefix custom components with a name unique to your company or application. For example, if a company named ABC creates a Card Panel component. The component's name space could be
abcCardPanel
.
Asset Type | Asset Name | Naming Scheme |
---|---|---|
Operation | Example and Round Average |
|
Input | Numbers |
|
Input | Round Number Decimals |
|
Create the manifest.json
File
The manfest.json file serves as the contract between Unqork and the operation implementation.
{
"name": "exAvgAndRound",
"version": "1.0.0",
"main": "exAvgAndRoundOperation.js",
"type": "custom",
"productType": "BYO",
"description": "A simple operation that averages an array of numbers and rounds result to specified decimals.",
"operations": [
{
"name": "Example Average and Round",
"type": "exAvgAndRound",
"description": "Averages an array of numbers and rounds result to specified decimals.",
"stability": "STABLE",
"model": {
"type": "object",
"properties": {
"options": {
"type": "object",
"properties": {
"numbers": {
"name": "Numbers",
"type": "array",
"description": "Flat array of numbers to average.",
"items": { "type": "number" },
"default": []
},
"roundNumDec": {
"name": "Round Number Decimals",
"type": "integer",
"description": "Number of decimals to round result.",
"minimum": 0,
"maximum": 10,
"default": 2,
"placeholder": "specify an integer between 0 and 10"
}
}
},
"type": {
"const": "exAvgAndRound",
"type": "string"
}
}
},
"contextModel": {
"type": "object",
"properties": {
"result": {
"type": "object",
"properties": {
"result": {
"name": "Result",
"type": "number",
"description": "Result of the average operation."
}
}
}
}
}
}
]
}
The following fields are used at the root level of the manifest:
Field | Type | Required | Description |
---|---|---|---|
name | string | A unique identifier for the package. For example, | |
version | string | The semantic version number. For example, | |
type | enum | The package type. Currently, the only supported value is | |
productType | enum | The target platform feature. Currently, the only supported value is | |
description | string | A description that displays in the Admin Panel after installation. | |
main | string | The relative path to the JavaScript entry file. For example, | |
components | array<component-description> | Optional | A list of component definitions included in the package. |
events | array<event-description> | Optional | List of event definitions. |
operations | array<operation-description> | Optional | List of operation definitions |
Understanding the Operations[0]
(The exAvgAndRound
Operation)
This is the main definition for the operation itself.
Property | Description | |
---|---|---|
| Define the component's name and its internal identifier. The type ( | |
| This object defines the number array and decimal rounding inputs that a user can configure when using this operation. | |
↳ |
| This is an input field for a user to provide an array of numbers. The schema specifies that it must be an array of number types. By default, this is an empty array. |
| This input field is for the number of decimal places for rounding. The schema specifies that it must be an integer between By default, this value is | |
| This is a schema that defines the output of the operation. It tells the Unqork platform what data to expect back so it can be used in subsequent steps of a workflow. | |
↳ |
| This field specifies that the operation will return an object with a single property named result, which is a number. |
Implement the Average and Round Operation
For this example, create a file called exAvgAndRoundOperation.js
. In this file, create an operation that does the following:
Defines the data model for the operation.
Averages the operation’s input values and rounds them to the specified decimal value.
Defines the operation’s data structure for the returned value.
Defines the return values in an export object.
Review the code example below for more information on each method:
The comments in the JavaScript below are written in the JSDoc format. For more information on JSDoc block tags (@param, @return), visit the JSDoc website: https://jsdoc.app/.
// Operation options
class ExAvgAndRoundOptions {
// Flat array of numbers to average. Defaults to an empty array
numbers = []
// Integer decimals (0..10) to round the result. Defaults to 2
roundNumDec = 2
}
// Operation model
class ExAvgAndRoundOperation {
// MUST match the manifest "type" and the named export below
type = 'exAvgAndRound'
options = new ExAvgAndRoundOptions()
}
// Operation handler
class ExAvgAndRoundHandler {
/**
* Execute the operation.
* @param {ExAvgAndRoundOperation} operation
* @param {*} api Operation API: { state: { resolveByKey, set, get }, events: { emit } }
* @returns {{ result: number }}
*/
async execute(operation, api) {
// Get the operation options or default to an empty object
const opts = operation.options.config ?? {}
// Extract the numbers array from the options
const nums = opts.numbers
// Calculate the mean (average).
// The result is either 0 (if the array is empty) or the calculated mean of the numbers.
const mean = nums.length === 0 ? 0 : nums.reduce((acc, n) => acc + n, 0) / nums.length
// Round the mean to the specified number of decimals
// Javascript method toFixed returns a string so it needs to be coerced back to number
const decimals = opts.roundNumDec
const result = Number(mean.toFixed(decimals))
return { result }
}
}
// Context result (what the op returns into context)
// If the operation handler does not return a result. This can be omitted.
class ExAvgAndRoundContextResult {
result = 0
}
// If the operation handler does not return a result. This can be omitted.
class ExAvgAndRoundContext {
result = new ExAvgAndRoundContextResult()
}
// Export for the operation
// Named export MUST match manifest "type"
export const exAvgAndRound = {
model: async () => ExAvgAndRoundOperation,
handler: async () => ExAvgAndRoundHandler,
contextModel: async () => ExAvgAndRoundContext, // If the operation handler does not return a result. This can be omitted.
}
Understanding ExAvgAndRoundOptions
and ExAvgAndRoundOperation
These classes define the data model for the operation's configuration.
Class | Description | |
---|---|---|
| Specifies the | |
↳ |
| An array of numbers to be averaged. It defaults to an empty array. |
| An integer that specifies how many decimal places to round the final result to. Default is | |
| Defines the overall operation model, linking the options to the operation's type, which must match the export name. |
Understanding ExAvgAndRoundHandler
This is the core logic of the operation. The execute
method runs when the operation is called.
Class | Description |
---|---|
| Specifies the two input parameters:
|
| Calculates the average (mean) of the numbers provided in the |
| Rounds the calculated Since JavaScript's |
| This returns the final calculated and rounded value. |
Understanding ExAvgAndRoundContextResult
and ExAvgAndRoundContext
These classes define the structure of the data the operation returns when it's completed. Doing so allows the result to be used in subsequent steps in an Unqork workflow.
The contextModel
is what enables other parts of the application to access the result
value.
Understanding the exAvgAndRound
Export
The final export object, exAvgAndRound
, is the manifest that binds everything together. It tells the Unqork platform where to find the operation's data model (model
), its logic (handler
), and the structure of its return value (contextModel
).
Create the BYO Operation Package
After the asset JavaScript and manifest.json files are complete, compress them into a BYO package.
To compile a file using Terminal (Mac) or Command Prompt (Windows):
Using the command line prompt, navigate to the directory containing the
exAvgAndRoundOperation.js
andmanifest.json
files. For example,cd C:\Users\UserName\Desktop\exAvgAndRoundOperation
.Execute the following command:
tar -cvzf exAvgAndRoundOperation.tar.gz manifest.json exAvgAndRoundOperation.js
.
A static image displaying the Terminal and the tar.gz prompt.
The exAvgAndRoundOperation.js
file and manifest.json
add to the tar.gz
file in the same folder they're located in.
NOTE
The steps above use the tar command and the following options:
-c
: Creates a new archive.
-z
: Compresses the archive using gzip.
-v
: Lists the files in the command line as they are added to archive.
-f
: Specifies the file name for the archived files.
Upload the BYO Operation Package
After creating the exAvgAndRound.tar.gz
package, upload it to the Unqork Designer Platform using the Custom Assets Administration page:
From the UDesigner homepage, click Administration.
Under Assets, click Custom Assets Administration.
Click + Create New. The Create Asset modal displays.
Under File Upload, click or drag the BYO Operation package from your local device to the upload window.
Click Scan File. The package details display.
Click Review Assets.
Review the asset's details, including Components, Events, and Operations.
Click Confirm & Create.
Review the Library Usage Acknowledgment and Liability Agreement. Click the ☐ (checkbox) to acknowledge the agreement.
Click Create Asset.
The asset package displays in the Custom Assets’ Packages list. The package's individual assets display in the Assets tab's Assets list. The assets are now available in the Module Builder for all applications in the environment.
Test the Average and Round Operation
Now that the BYO Average and Round Operation is in the Unqork Designer Platform, test its functionality in the Module Builder and Express View. This example assumes you are configuring a Vega (2.0) module.
For this example, enter the following functions:
Average: Verify that the operation averages the numbers array contained in the configuration.
Round: Verify the operation rounds to the decimal value specified in the configuration.
Configure the Text Field Component
Configure a Text Field component to receive the operation’s results.
In the Module Builder, drag and drop a Text Field component onto your canvas.
In the Property ID field, enter
results
.In the Label Text field, enter
Result
.Click Save Component.
Configure the Button Component
Configure a Button component to trigger the average and round operation. When end-users click on the button, an event is emitted and the Average and Round operation executes.
Drag and drop a Button component onto your canvas.
In the Property ID field, enter
btnCalculate
.In the Label Text field, enter
Calculate
.Navigate to the Actions settings.
Set Action Type to Event.
Configure the btnCalculate Events and Operations
While remaining in the Button component’s configuration drawer, open the Operations Builder. Set up an On Click event to trigger the BYO exAvgAndRound
operation. Set up the operation to average a set of values, then round the decimal to the third.
For this example, average the following values 2
, 4
, 8
, 5
, 23
, 7
, and a rounding value of 3
.
Next to Events & Operations, click Edit.
From the Select an Event drop-down, enter or select On Click.
Click Add.
Click + Add Operation.
From the Operation Type drop-down, select Example Average and Round.
In the Operation Name field, enter
exAvgAndRound
.In the Config field, enter
{"numbers":[2,4,8,5,23,7],"roundNumDec":3}
.Click Save.
Click + Add Operation.
From the Operation Type drop-down, select Set Property.
In the Target Key field, enter
results
. This sends the operation’s output to theresults
Text Field component.In the Property field, enter
value
.In the Value field, enter
{{ $operationContext.exAvgAndRound.result.result}}
. This dynamic value becomes the final value after the operation executes its calculations.Click Save.
Click Close.
Click Save Component.
Save your module.
Your completed module looks like the following:
Preview and Test the Module
Lastly, test your configuration and verify that the operation outputs the correct value. The decimal should round to the thousandths place.
Preview your module in Express View.
Click the Calculate button.
In the Result field, verify that the return value is
8.167
.
If the custom asset functions as intended, then it’s ready to be used by Creators in the development of Unqork applications.
If the Custom Operation generates errors or is missing features:
Create a copy of the current package and its contents.
Update the package's required files.
Change the package's version number.
Update the package by referring to the Package Management section in our BYO Best Practices article.