浏览代码

feat: add functions in reference data

Ahmad Kholid 3 年之前
父节点
当前提交
71f45120d6

+ 3 - 8
src/background/workflow-engine/blocks-handler/handler-conditions.js

@@ -1,7 +1,6 @@
 import { getBlockConnection } from '../helper';
-import { replaceMustache } from '@/utils/helper';
-import { replaceMustacheHandler } from '@/utils/reference-data';
 import compareBlockValue from '@/utils/compare-block-value';
+import mustacheReplacer from '@/utils/reference-data/mustache-replacer';
 
 function conditions({ data, outputs }, { prevBlockData, refData }) {
   return new Promise((resolve, reject) => {
@@ -13,7 +12,6 @@ function conditions({ data, outputs }, { prevBlockData, refData }) {
     let resultData = '';
     let isConditionMatch = false;
     let outputIndex = data.conditions.length + 1;
-    const handleMustache = (match) => replaceMustacheHandler(match, refData);
     const prevData = Array.isArray(prevBlockData)
       ? prevBlockData[0]
       : prevBlockData;
@@ -21,11 +19,8 @@ function conditions({ data, outputs }, { prevBlockData, refData }) {
     data.conditions.forEach(({ type, value, compareValue }, index) => {
       if (isConditionMatch) return;
 
-      const firstValue = replaceMustache(
-        compareValue ?? prevData,
-        handleMustache
-      );
-      const secondValue = replaceMustache(value, handleMustache);
+      const firstValue = mustacheReplacer(compareValue ?? prevData, refData);
+      const secondValue = mustacheReplacer(value, refData);
 
       const isMatch = compareBlockValue(type, firstValue, secondValue);
 

+ 1 - 1
src/background/workflow-engine/engine.js

@@ -351,7 +351,7 @@ class WorkflowEngine {
         googleSheets: this.googleSheets,
         activeTabUrl: this.activeTabUrl,
       };
-      const replacedBlock = referenceData(block, refData);
+      const replacedBlock = referenceData({ block, data: refData });
       const blockDelay =
         block.name === 'trigger' ? 0 : this.workflow.settings?.blockDelay || 0;
 

+ 0 - 74
src/utils/reference-data.js

@@ -1,74 +0,0 @@
-import { get, set } from 'object-path-immutable';
-import { isObject, objectHasKey, replaceMustache } from '@/utils/helper';
-
-const objectPath = { get, set };
-const refKeys = [
-  { name: 'dataColumn', key: 'dataColumns' },
-  { name: 'dataColumns', key: 'dataColumns' },
-];
-
-export function parseKey(key) {
-  /* eslint-disable-next-line */
-  let [dataKey, path] = key.split('@');
-
-  dataKey =
-    (refKeys.find((item) => item.name === dataKey) || {}).key || dataKey;
-
-  if (dataKey !== 'dataColumns') return { dataKey, path: path || '' };
-
-  const pathArr = path?.split('.') ?? [];
-  let dataPath = path;
-
-  if (pathArr.length === 1) {
-    dataPath = `0.${pathArr[0]}`;
-  } else if (typeof +pathArr[0] !== 'number' || Number.isNaN(+pathArr[0])) {
-    dataPath = `0.${pathArr.join('.')}`;
-  }
-
-  if (dataPath.endsWith('.')) dataPath = dataPath.slice(0, -1);
-
-  return { dataKey: 'dataColumns', path: dataPath };
-}
-export function replaceMustacheHandler(match, data) {
-  const key = match.slice(2, -2).replace(/\s/g, '');
-
-  if (!key) return '';
-
-  const { dataKey, path } = parseKey(key);
-  const result = objectPath.get(data[dataKey], path) ?? match;
-
-  return isObject(result) ? JSON.stringify(result) : result;
-}
-
-export default function (block, data) {
-  const replaceKeys = [
-    'url',
-    'name',
-    'body',
-    'value',
-    'fileName',
-    'selector',
-    'prefixText',
-    'globalData',
-    'suffixText',
-    'extraRowValue',
-  ];
-  let replacedBlock = block;
-
-  replaceKeys.forEach((blockDataKey) => {
-    if (!objectHasKey(block.data, blockDataKey)) return;
-
-    const newDataValue = replaceMustache(
-      replacedBlock.data[blockDataKey],
-      (match) => replaceMustacheHandler(match, data)
-    );
-
-    replacedBlock = objectPath.set(
-      replacedBlock,
-      `data.${blockDataKey}`,
-      newDataValue
-    );
-  });
-
-  return replacedBlock;
-}

+ 61 - 0
src/utils/reference-data/index.js

@@ -0,0 +1,61 @@
+import { set as setObjectPath } from 'object-path-immutable';
+import dayjs from 'dayjs';
+import { objectHasKey } from '@/utils/helper';
+import mustacheReplacer from './mustache-replacer';
+
+export const funcs = {
+  date: (...params) => {
+    let date = new Date();
+    let dateFormat = 'DD-MM-YYYY';
+
+    const getDateFormat = (value) =>
+      value ? value?.replace(/['"]/g, '') : dateFormat;
+
+    if (params.length === 1) {
+      dateFormat = getDateFormat(params[0][0]);
+    } else if (params.length >= 2) {
+      date = new Date(params[0]);
+      dateFormat = getDateFormat(params[1][0]);
+    }
+
+    /* eslint-disable-next-line */
+    const isValidDate = date instanceof Date && !isNaN(date);
+    const result = dayjs(isValidDate ? date : Date.now()).format(dateFormat);
+
+    return result;
+  },
+};
+
+export default function ({ block, data }) {
+  const replaceKeys = [
+    'url',
+    'name',
+    'body',
+    'value',
+    'fileName',
+    'selector',
+    'prefixText',
+    'globalData',
+    'suffixText',
+    'extraRowValue',
+  ];
+  let replacedBlock = { ...block };
+  const refData = Object.assign(data, { funcs });
+
+  replaceKeys.forEach((blockDataKey) => {
+    if (!objectHasKey(block.data, blockDataKey)) return;
+
+    const newDataValue = mustacheReplacer(
+      replacedBlock.data[blockDataKey],
+      refData
+    );
+
+    replacedBlock = setObjectPath(
+      replacedBlock,
+      `data.${blockDataKey}`,
+      newDataValue
+    );
+  });
+
+  return replacedBlock;
+}

+ 28 - 0
src/utils/reference-data/key-parser.js

@@ -0,0 +1,28 @@
+import { objectHasKey } from '../helper';
+
+const refKeys = {
+  dataColumn: 'dataColumns',
+  dataColumns: 'dataColumns',
+};
+
+export default function (key) {
+  /* eslint-disable-next-line */
+  let [dataKey, path] = key.split('@');
+
+  dataKey = objectHasKey(refKeys, dataKey) ? refKeys[dataKey] : dataKey;
+
+  if (dataKey !== 'dataColumns') return { dataKey, path: path || '' };
+
+  const pathArr = path?.split('.') ?? [];
+  let dataPath = path;
+
+  if (pathArr.length === 1) {
+    dataPath = `0.${pathArr[0]}`;
+  } else if (typeof +pathArr[0] !== 'number' || Number.isNaN(+pathArr[0])) {
+    dataPath = `0.${pathArr.join('.')}`;
+  }
+
+  if (dataPath.endsWith('.')) dataPath = dataPath.slice(0, -1);
+
+  return { dataKey: 'dataColumns', path: dataPath };
+}

+ 35 - 0
src/utils/reference-data/mustache-replacer.js

@@ -0,0 +1,35 @@
+import { get as getObjectPath } from 'object-path-immutable';
+import { replaceMustache, isObject } from '../helper';
+import keyParser from './key-parser';
+
+export function extractStrFunction(str) {
+  const extractedStr = /^\$\s*(\w+)\s*\((.*)\)/.exec(str.trim());
+
+  if (!extractedStr) return null;
+
+  return {
+    name: extractedStr[1],
+    params: extractedStr[2].split(','),
+  };
+}
+
+export default function (str, data) {
+  const replacedStr = replaceMustache(str, (match) => {
+    const key = match.slice(2, -2).replace(/\s/g, '');
+
+    if (!key) return '';
+
+    const funcRef = extractStrFunction(key);
+
+    if (funcRef && data.funcs[funcRef.name]) {
+      return data.funcs[funcRef.name]?.(funcRef.params);
+    }
+
+    const { dataKey, path } = keyParser(key);
+    const result = getObjectPath(data[dataKey], path) ?? match;
+
+    return isObject(result) ? JSON.stringify(result) : result;
+  });
+
+  return replacedStr;
+}