handlerExecuteWorkflow.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import browser from 'webextension-polyfill';
  2. import { isWhitespace, parseJSON } from '@/utils/helper';
  3. import decryptFlow, { getWorkflowPass } from '@/utils/decryptFlow';
  4. import convertWorkflowData from '@/utils/convertWorkflowData';
  5. import WorkflowEngine from '../WorkflowEngine';
  6. function workflowListener(workflow, options) {
  7. return new Promise((resolve, reject) => {
  8. if (workflow.isProtected) {
  9. const flow = parseJSON(workflow.drawflow, null);
  10. if (!flow) {
  11. const pass = getWorkflowPass(workflow.pass);
  12. workflow.drawflow = decryptFlow(workflow, pass);
  13. }
  14. }
  15. const engine = new WorkflowEngine(workflow, options);
  16. engine.init();
  17. engine.on('destroyed', ({ id, status, message }) => {
  18. console.log(engine.referenceData.table, engine.referenceData.variables);
  19. options.events.onDestroyed(engine);
  20. if (status === 'error') {
  21. const error = new Error(message);
  22. error.data = { logId: id };
  23. reject(error);
  24. return;
  25. }
  26. resolve({ id, status, message });
  27. });
  28. options.events.onInit(engine);
  29. });
  30. }
  31. function findWorkflow(workflows, workflowId) {
  32. const workflow = Array.isArray(workflows)
  33. ? workflows.find(({ id }) => id === workflowId)
  34. : workflows[workflowId];
  35. return workflow;
  36. }
  37. async function executeWorkflow({ id: blockId, data }) {
  38. if (data.workflowId === '') throw new Error('empty-workflow');
  39. const { workflows, teamWorkflows } = await browser.storage.local.get([
  40. 'workflows',
  41. 'teamWorkflows',
  42. ]);
  43. let workflow = null;
  44. if (data.workflowId.startsWith('team')) {
  45. const teamWorkflowsArr = Object.values(
  46. Object.values(teamWorkflows || {})[0] ?? {}
  47. );
  48. workflow = findWorkflow(teamWorkflowsArr, data.workflowId);
  49. } else {
  50. workflow = findWorkflow(workflows, data.workflowId);
  51. }
  52. if (!workflow) {
  53. const errorInstance = new Error('no-workflow');
  54. errorInstance.data = { workflowId: data.workflowId };
  55. throw errorInstance;
  56. }
  57. workflow = convertWorkflowData(workflow);
  58. const optionsParams = { variables: {} };
  59. if (!isWhitespace(data.globalData))
  60. optionsParams.globalData = data.globalData;
  61. if (data.insertAllVars) {
  62. optionsParams.variables = JSON.parse(
  63. JSON.stringify(this.engine.referenceData.variables)
  64. );
  65. } else if (data.insertVars) {
  66. const varsName = data.insertVars.split(',');
  67. varsName.forEach((name) => {
  68. const varName = name.trim();
  69. const value = this.engine.referenceData.variables[varName];
  70. if (!value && typeof value !== 'boolean') return;
  71. optionsParams.variables[varName] = value;
  72. });
  73. }
  74. const options = {
  75. options: {
  76. data: optionsParams,
  77. parentWorkflow: {
  78. id: this.engine.id,
  79. name: this.engine.workflow.name,
  80. },
  81. },
  82. events: {
  83. onInit: (engine) => {
  84. this.childWorkflowId = engine.id;
  85. },
  86. onDestroyed: (engine) => {
  87. if (data.executeId) {
  88. const { variables, table } = engine.referenceData;
  89. this.engine.referenceData.workflow[data.executeId] = {
  90. table,
  91. variables,
  92. };
  93. }
  94. },
  95. },
  96. states: this.engine.states,
  97. logger: this.engine.logger,
  98. blocksHandler: this.engine.blocksHandler,
  99. };
  100. const isWorkflowIncluded = workflow.drawflow.nodes.some(
  101. (node) =>
  102. node.label === 'execute-workflow' &&
  103. node.data.workflowId === this.engine.workflow.id
  104. );
  105. if (isWorkflowIncluded) {
  106. throw new Error('workflow-infinite-loop');
  107. }
  108. const result = await workflowListener(workflow, options);
  109. return {
  110. data: '',
  111. logId: result.id,
  112. nextBlockId: this.getBlockConnections(blockId),
  113. };
  114. }
  115. export default executeWorkflow;