JavaScript Fields Mappings and Comparators

Some fields are supported by default. In case any additional custom behaviour is required, use JavaScript mappings. Remember that JavaScript mappings need a custom comparator to be added in order to be considered in data validation reporting.

Arguments

JavaScript mapping script receives the following arguments

export interface IExecuteParamsArgs {
  account: string
  /// Metadata of updated field from the tool where an update is coming from
  sourceField: FieldDefRef
  /// Contains the original and changed value of sourceField
  value: {
    changed: unknown
    original: unknown
  }
  /// Metadata of the field which will be updated
  targetField: FieldDefRef
  /// Reference of an entity from the tool where an update is coming from
  sourceEntity: EntityRef
  /// Description of the source entity change.
  /// May contain current and previous state of an entity, modification,
  /// array of changed fields
  sourceEntityModification: {
    changed: { [key: string]: any } | undefined
    original: { [key: string]: any } | undefined
    modification: EntityModification | undefined
    changedFields: string[] | undefined
  }
  /// Reference of the entity to which the field update will be applied
  targetEntity: EntityRef
  /// Information about the tool where an update is coming from
  sourceTool: ToolRef
  /// Information about the tool where an update will be applied
  targetTool: ToolRef
}

sourceEntityModification

The object contains the information about the entity before and after the change. For state transfer events original is undefined.

Sync guarantees that only fields configured in the field mappings will be presented in changed object.

Using JavaScript and WorkSharing API you can do different kinds of transformations.

Return value

JavaScript field mapping can return an object of type JavaScriptExecutionResult or an array of such objects. Definition of JavaScriptExecutionResult:

type JavaScriptExecutionResult =
  | {
      kind:  'Value'
      value: unknown
      options?: FieldModificationOptions
    }
  | {
      kind: 'Update'
      fieldModifications: FieldModification[]
    }
  | {
      kind: 'RelationAdded' | 'RelationRemoved'
      relation: EntityRelation
    }
  | {
      kind: 'Retry'
      reason?: string
    }

Full definition of types can be found at https://{{account_name}}.tpondemand.com/svc/js-executor/types

In the code sections below you can find examples of return values of JavaScript field mapping:

{
  kind: 'Value',
  // this value will be applied to args.targetField
  value: 'new value',
  options: {
    applyRawValue: true
  }
}
{
  kind: 'Update',
  fieldModifications: [{
    // definition of field to update
    fieldDef: field1FieldDef,
    value: 'new value'
   },  
   {
    // definition of field to update
    fieldDef: field2FieldDef,
    value: 'new value 2'
   }],
}
// This command will add a relation with id 42 
// between args.targetEntity and entity with id 123 of type Task
{
  kind: 'RelationAdded',
  relation: {
    entityType: 'Task',
    sourceId: '123',
    relationType: '42'
  }
}
// Retry result kind allows retrying execution of field mapping. 
// It can be useful in cases when the tool's API throttles clients by returning 429 status code or temporarily unavailable 
{
  kind: 'Retry'
  reason: 'Jira is unavailable
}

FieldModificationOptions

For Value and Update return value kinds you can pass an additional applyRawValue option. Issue Level Integration support resolution of reference fields by name. For example, you can update the team/feature or another reference field by returning the object's Name. applyRawValue parameter disables this behaviour

Comparators

You have to write a comparator script for every JavaScript mapping to make sync report work correctly for a field mapping. The comparator script receives args object as a parameter with the following interface:

interface IJSCustomComparatorArgs {
  account: string
  // sourceFieldValue contains different representations of fieldMapping's source field
  sourceFieldValue: {
    // Contains string representation of the field. String representation may differ depending on field type
    toolStringValue: string
    // Contains value as it is used in integration
    // For example, for some of the fields type of rawValue is number, but the type of toolValue is string
    toolValue: any
    // Contains field's value as it is stored in tool
    rawValue: any
    fieldDef: FieldDefRef
  }
  // targetFieldValue contains different representations of fieldMapping's target field
  targetFieldValue: {
    toolStringValue: string
    toolValue: any
    rawValue: any
    fieldDef: FieldDefRef
  }
  sourceField: FieldDefRef
  targetField: FieldDefRef
  sourceEntity: EntityRef
  targetEntity: EntityRef
  sourceEntityState: ToolEntityState
  targetEntityState: ToolEntityState
  sourceTool: ToolRef
  targetTool: ToolRef
}

Full definition of types can be found at https://{{account_name}}.tpondemand.com/svc/js-executor/types

Return value

Script must return true when the value of source field is equal to the value of target field. false should be returned otherwise.

Recommendations

To maximize the performance of JavaScript field mappings, and comparators and decrease the load on your Jira/Azure DevOps/Targetprocess instance, try to minify the number of HTTP requests your scripts do using HttpApi

Examples

Example: Map Jira Worklog (recent total times) to Targetprocess Time record.

Example: Map Jira Status to Targetprocess Team States.

More examples in GitHub library of JS mappings and routings samples.