Name

sn_now_list_common.ListTransformUtils

Description

No description available

Script

var ListTransformUtils = Class.create();
ListTransformUtils.prototype = (function() {
  function initialize() {
  }

  function cloneDeep(x) {
      if (typeof x !== 'object') return x;

      var k, tmp, str=Object.prototype.toString.call(x);

      if (str === '[object Object]') {
          if (x.constructor !== Object && typeof x.constructor === 'function') {
              tmp = new x.constructor();
              for (k in x) {
                  if (x.hasOwnProperty(k) && tmp[k] !== x[k]) {
                      tmp[k] = cloneDeep(x[k]);
                  }
              }
          } else {
              tmp = {}; // null
              for (k in x) {
                  if (k === '__proto__') {
                      Object.defineProperty(tmp, k, {
                          value: cloneDeep(x[k]),
                          configurable: true,
                          enumerable: true,
                          writable: true,
                      });
                  } else {
                      tmp[k] = cloneDeep(x[k]);
                  }
              }
          }
          return tmp;
      }

      if (str === '[object Array]') {
          k = x.length;
          for (tmp=Array(k); k--;) {
              tmp[k] = cloneDeep(x[k]);
          }
          return tmp;
      }

      if (str === '[object Date]') {
          return new Date(+x);
      }

      if (str === '[object RegExp]') {
          tmp = new RegExp(x.source, x.flags);
          tmp.lastIndex = x.lastIndex;
          return tmp;
      }

      return x;
  }

  function validateTransformedCollection(initialMap, transformed, type) {
      var finalItems = [];
      
      // reconcile rows & columns. no adding/removing rows. no adding columns
      var transformedMap = {};
      transformed.forEach(function (item) {
          transformedMap[item.key] = item;
      });

      // Iterate through the initialRowsMap keys
      for (var key in initialMap) {
          // Check if the item exists in the transformed items
          var foundItem = transformedMap[key];

          // If the initial item exists in the transformed items, add it to finalItems
          if (foundItem) {
              finalItems.push(foundItem);
          }
          // if its a row and we didnt find the initial item in the transformed items, add it back
          else if (type === 'row') {
              gs.warn(`Transformation Script: Removing ${type}s in the transform script is not supported. Adding initial ${type} back. key = ${key}`);
              finalItems.push(initialMap[key]);
          }
      }
      if (Object.keys(transformedMap).length > Object.keys(initialMap).length) {
          gs.warn(`Transformation Script: Adding ${type}s in the transform script is not supported. Removing ${type}.`);
      }
      return finalItems;
  }

  function processTransform(transformScriptSysId, preTransformData) {
      var transformResult = null;
      var scriptFailedMessage = "Transformation script failed. ";
      var checkLogsMessage = "Please check debug logs for more details.";
      
      var gr = new GlideRecord('sys_script_include');
      var transformFound = gr.get(transformScriptSysId);

      if (!transformFound) {
          return preTransformData;
      }

      // Create maps of the initial rows and columns to reconcile after transform
      var initialRowsMap = 
          this.cloneDeep(preTransformData.rowDefinitions.rows)
              .reduce(function(map, row) {
                  map[row.key] = row;
                  return map;
              }, {});

      var initialColumnsMap = 
          this.cloneDeep(preTransformData.columnDefinitions.columns)
              .reduce(function(map, col) {
                  map[col.key] = col;
                  return map;
              }, {});
      
      var evaluator = new GlideScopedEvaluator();
      var declarativeActions = preTransformData.declarativeActions;

      // passing in declarative actions by reference on purpose
      // we dont expose these to the user in the builder because we dont want them manually messing
      // with the raw declarative actions model, they only can mutate this by using the api
      var transformBuilder = new sn_now_list_common.ListTransformScriptBuilder(declarativeActions.declarativeActions)
          .setRowDefinitions(preTransformData.rowDefinitions)
          .setColumnDefinitions(preTransformData.columnDefinitions);


      evaluator.putVariable('transformBuilder', transformBuilder);
      transformResult = evaluator.evaluateScript(gr, 'script', null);

      // transform script error but try/catch not present in transform script so cant catch
      if (!transformResult) {
          throw new Error(scriptFailedMessage + checkLogsMessage);
      }
      // try / catch added in our default transform template is handled here
      if (transformResult.failed === true) {
          throw new Error(scriptFailedMessage + transformResult.error);
      }

      // reconcile rows. no adding/removing rows
      var validatedRows = validateTransformedCollection(
                                                  initialRowsMap,
                                                  transformResult.rowDefinitions.rows,
                                                  'row'
                                              );
      transformResult.rowDefinitions.rows = validatedRows;

      // reconcile columns. no adding columns.
      var validatedColumns = validateTransformedCollection(
                                                  initialColumnsMap,
                                                  transformResult.columnDefinitions.columns,
                                                  'column'
                                              );
      transformResult.columnDefinitions.columns = validatedColumns;

      return {
          columnDefinitions: transformResult.columnDefinitions,
          rowDefinitions: transformResult.rowDefinitions,
          declarativeActions: declarativeActions,
          encodedQuery: preTransformData.encodedQuery,
          pagination: preTransformData.pagination,
          tableLabel: preTransformData.tableLabel,
          tableMetadata: preTransformData.tableMetadata
      };
  }

  return {
      initialize: initialize,
      cloneDeep: cloneDeep,
      processTransform: processTransform,
      type: 'ListTransformUtils'
  };

})();

Sys ID

c924b0930a62a510f87c7eba8d4653dd

Offical Documentation

Official Docs: