Socket
Socket
Sign inDemoInstall

@automa-app/core

Package Overview
Dependencies
6
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.9.1 to 0.9.3

2

dist/automa-core.cjs.js

@@ -1,1 +0,1 @@

"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("nanoid"),t=require("os"),s=require("@automa/shared"),a=require("lodash.clonedeep"),i=require("unstorage"),r=require("object-path");function o(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var n=o(t),l=o(a),c=o(r);const h=i.createStorage();class d{constructor(){this.eventListeners={}}dispatchEvent(e,t){const s=this.eventListeners[e];s&&s.forEach((e=>{e(t)}))}on(e,t){(this.eventListeners[e]=this.eventListeners[e]||[]).push(t)}off(e,t){const s=this.eventListeners[e];if(!s)return;const a=s.indexOf(t);-1!==a&&s.splice(a,1)}}class u{constructor(t){this.id=e.nanoid(5),this.engine=t,this.options=this.engine.options,this.browser=this.engine.browser,this.settings=t.workflow.settings,this.pages=[],this.loopList={},this.repeatedTasks={},this.preloadScripts=[],this.windowId=null,this.currentBlock=null,this.childWorkflowId=null,this.activeTab={url:"",frameId:0,frames:{},groupId:null,id:t.options?.tabId}}init({blockId:e,prevBlockData:t,state:s}){s&&Object.keys(s).forEach((e=>{this[e]=s[e]}));const a=this.engine.blocks[e];this.executeBlock(a,t)}addDataToColumn(e,t){if(Array.isArray(e))return void e.forEach((e=>{s.isObject(e)&&Object.entries(e).forEach((([e,t])=>{this.addDataToColumn(e,t)}))}));const a=(this.engine.columns[e]?e:this.engine.columnsId[e])||"column",i=this.engine.columns[a],r=i.name||"column",o=s.convertData(t,i.type);s.objectHasKey(this.engine.referenceData.table,i.index)?this.engine.referenceData.table[i.index][r]=o:this.engine.referenceData.table.push({[r]:o}),i.index+=1}setVariable(e,t){this.engine.referenceData.variables[e]=t}executeNextBlocks(e,t){e.forEach((({node:e},s)=>{if(0===s)this.executeBlock(this.engine.blocks[e],t);else{const s=l.default({windowId:this.windowId,loopList:this.loopList,activeTab:this.activeTab,currentBlock:this.currentBlock,repeatedTasks:this.repeatedTasks,preloadScripts:this.preloadScripts});this.engine.addWorker({state:s,prevBlockData:t,blockId:e})}}))}async executeBlock(e,t,a){const i=await this.engine.states.get(this.engine.id);if(!i||i.isDestroyed){if(this.engine.isDestroyed)return;return void await this.engine.destroy("stopped")}const r=this.currentBlock;this.currentBlock=e,a||await this.engine.updateState({activeTabUrl:this.activeTab.url,childWorkflowId:this.childWorkflowId});const o=this.engine.blocksHandler[s.toCamelCase(e.name)],n=o||"interaction"!==s.blocks[e.name].category?o:this.engine.blocksHandler.interactionBlock;if(!n)return void this.engine.destroy("stopped",`${e.name} doesn't have handler`);const l={prevBlockData:t,...this.engine.referenceData,activeTabUrl:this.activeTab.url},h=function({block:e,refKeys:t,data:a}){if(!t||0===t.length)return e;const i=JSON.parse(JSON.stringify(e)),r=e=>{i.replacedValue||(i.replacedValue={}),i.replacedValue={...i.replacedValue,...e}};return t.forEach((e=>{const t=c.default.get(i.data,e);if(t)if(Array.isArray(t))t.forEach(((t,o)=>{const n=s.mustacheReplacer(t,a);r(n.list),c.default.set(i.data,`${e}.${o}`,n.value)}));else if("string"==typeof t){const o=s.mustacheReplacer(t,a);r(o.list),c.default.set(i.data,e,o.value)}})),i}({block:e,data:l,refKeys:a||e.data.disableBlock?null:s.blocks[e.name].refDataKeys}),d=this.settings?.blockDelay||0,u=Date.now(),p=(s,a={})=>{this.engine.addLogHistory({prevBlockData:t,type:s,name:e.name,workerId:this.id,description:e.data.description,replacedValue:h.replacedValue,duration:Math.round(Date.now()-u),...a})};try{let a;e.data.disableBlock?a={data:"",nextBlockId:s.getBlockConnection(e)}:(a=await n.call(this,h,{refData:l,prevBlock:r,prevBlockData:t}),a.replacedValue&&(h.replacedValue=a.replacedValue),p(a.status||"success",{logId:a.logId}));let i=null;i="string"==typeof a.nextBlockId?[{node:a.nextBlockId}]:a.nextBlockId.connections,i.length>0&&!a.destroyWorker?setTimeout((()=>{this.executeNextBlocks(i,a.data)}),d):this.engine.destroyWorker(this.id)}catch(a){console.error(a);const{onError:i}=h.data;if(i&&i.enable){if(i.retry&&i.retryTimes)return await s.sleep(1e3*i.retryInterval),i.retryTimes-=1,void await this.executeBlock(h,t,!0);const a=s.getBlockConnection(e,"continue"===i.toDo?1:2);if("error"!==i.toDo&&a.connections)return void this.executeNextBlocks(a.connections,t)}p("error",{message:a.message,...a.data||{}});const{onError:r}=this.settings,o=a.nextBlockId?.connections;if("keep-running"===r&&o)setTimeout((()=>{this.executeNextBlocks(o,a.data||"")}),d);else if("restart-workflow"!==r||this.parentWorkflow)this.engine.destroy("error",a.message);else{if(this.engine.restartCount>=(this.settings.restartTimes??3))return void this.engine.destroy();this.reset();const e=Object.values(this.engine.blocks).find((({name:e})=>"trigger"===e));this.executeBlock(e),this.engine.restartCount+=1}}}reset(){this.loopList={},this.repeatedTasks={},this.windowId=null,this.currentBlock=null,this.childWorkflowId=null,this.engine.history=[],this.engine.preloadScripts=[],this.engine.columns={column:{index:0,name:"column",type:"any"}},this.activeTab={url:"",frameId:0,frames:{},groupId:null,id:this.options?.tabId},this.engine.referenceData={table:[],loopData:{},workflow:{},googleSheets:{},variables:this.engine.options.variables,globalData:this.engine.referenceData.globalData}}get activePage(){return"number"!=typeof this.activeTab.id||0===this.pages.length?null:this.pages[this.activeTab.id]}}class p extends d{constructor(t,{states:a,logger:i,blocksHandler:r,browser:o,parentWorkflow:l,options:c,storage:d=h}={}){super(),this.id=e.nanoid(),this.states=a,this.logger=i,this.browser=o,this.storage=d,this.workflow=t,this.blocksHandler=r,this.parentWorkflow=l,this.saveLog=t.settings?.saveLog??!0,this.restartCount=0,this.triggerBlock=null,this.isDestroyed=!1,this.isUsingProxy=!1,this.workers=new Map,this.waitConnections={},this.blocks={},this.history=[],this.columnsId={},this.historyCtxData={},this.eventListeners={},this.columns={column:{index:0,type:"any",name:this.workflow.settings?.defaultColumnName||"column"}};let u={},{globalData:p}=t;c&&c?.data&&(p=c.data.globalData,u=s.isObject(c.data.variables)?c?.data.variables:{},c.data={globalData:p,variables:u}),this.options={exportPath:n.default.homedir(),...c||{}},this.referenceData={variables:u,table:[],loopData:{},workflow:{},googleSheets:{},globalData:s.parseJSON(p,p)},this.onWorkflowStopped=e=>{this.id!==e||this.isDestroyed||this.stop()}}init(){if(this.workflow.isDisabled)return;if(!this.blocksHandler)throw new Error("Doesn't have blocks handler");if(!this.states)throw new Error(`"${this.workflow.name}" workflow doesn't have states`);const{drawflow:e}=this.workflow,t=s.parseJSON(e,e)?.drawflow?.Home.data;if(!t)throw new Error(`${this.workflow.name} doesn't have blocks`);const a=Object.values(t).find((({name:e})=>"trigger"===e));if(!a)throw new Error(`${this.workflow.name} doesn't have a trigger block`);this.workflow.table.forEach((({name:e,type:t,id:s})=>{const a=s||e;this.columnsId[e]=a,this.columns[a]={index:0,name:e,type:t}})),this.blocks=t,this.startedTimestamp=Date.now(),this.workflow.table=columns,this.states.on("stop",this.onWorkflowStopped),this.states.add(this.id,{state:this.state,workflowId:this.workflow.id,parentState:this.parentWorkflow}).then((()=>{this.addWorker({blockId:a.id})}))}async updateState(e){const t={...this.state,...e,tabIds:[],currentBlock:[]};this.workers.forEach((e=>{t.tabIds.push(e.activeTab.id),t.currentBlock.push(e.currentBlock)})),await this.states.update(this.id,{state:t}),this.dispatchEvent("update",{state:t})}addWorker(e){const t=new u(this);t.init(e),this.workers.set(t.id,t)}addLogHistory(t){if(!this.saveLog&&(this.history.length>=1001||"blocks-group"===t.name)&&"error"!==t.type)return;const a=e.nanoid();if(t.id=a,t.replacedValue||s.blocks[t.name]?.refDataKeys&&this.saveLog){const{activeTabUrl:e,variables:s,loopData:i,prevBlockData:r}=l.default(this.referenceData);this.historyCtxData[a]={referenceData:{loopData:i,variables:s,activeTabUrl:e,prevBlockData:r},replacedValue:t.replacedValue},delete t.replacedValue}this.history.push(t)}async stop(){this.childWorkflowId&&await this.states.stop(this.childWorkflowId),await this.destroy("stopped")}destroyWorker(e){this.workers.delete(e),0===this.workers.size&&(this.addLogHistory({type:"finish",name:"finish"}),this.dispatchEvent("finish"),this.destroy("success"))}async destroy(e,t){if(this.isDestroyed)return;this.workers.clear();const s=Date.now();if(!this.workflow.isTesting){const{name:a,id:i}=this.workflow;await this.logger.add({name:a,status:e,message:t,id:this.id,workflowId:i,history:this.saveLog?this.history:[],endedAt:s,parentLog:this.parentWorkflow,startedAt:this.startedTimestamp,data:{table:this.referenceData.table,variables:this.referenceData.variables}})}this.states.off("stop",this.onWorkflowStopped),await this.states.delete(this.id),this.dispatchEvent("destroyed",{status:e,message:t,id:this.id,currentBlock:this.currentBlock,logsCtxData:this.historyCtxData,referenceData:this.referenceData}),this.isDestroyed=!0,this.eventListeners={}}get state(){const e={name:this.workflow.name,icon:this.workflow.icon};return["columns","referenceData","startedTimestamp"].forEach((t=>{e[t]=this[t]})),e}}class f extends d{constructor({storage:e=h,key:t="workflowState"}={}){super(),this.key=t,this.storage=e,this.cache=null}async _updater(e,t){try{const s=e(await this.get());return await this.storage.setItem(this.key,s),t&&this.dispatchEvent(t.name,t.params),s}catch(e){return console.error(e),[]}}async get(e){try{let t=this.cache??(await this.storage.getItem(this.key)||{});return Array.isArray(t)&&(t={},await this.storage.setItem(this.key,{})),"function"==typeof e?t=Object.values(t).find(e):e?t=t[e]:this.cache=t,t}catch(e){return console.error(e),null}}add(e,t={}){return this._updater((s=>(s[e]={id:e,isPaused:!1,isDestroyed:!1,...t},s)))}async stop(e){return await this.update(e,{isDestroyed:!0}),this.dispatchEvent("stop",e),e}update(e,t={}){const s={name:"update",params:{id:e,data:t}};return this._updater((s=>(s[e]&&(s[e]={...s[e],...t}),s)),s)}delete(e){const t={name:"delete",params:e};return this._updater((t=>(delete t[e],t)),t)}}class k extends d{constructor({storage:e=h,key:t="logs"}={}){super(),this.key=t,this.storage=e}async add(e){const t=await this.storage.getItem(this.key)||[];t.unshift(e),await this.storage.setItem(this.key,t)}}exports.WorkflowEngine=p,exports.WorkflowLogger=k,exports.WorkflowStates=f,exports.executeWorkflow=function(e,{browser:t,blocksHandler:s,options:a}){const i=new f,r=new k;return new p(e,{states:i,logger:r,browser:t,blocksHandler:s,options:a||{}})};
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("nanoid"),t=require("os"),s=require("@automa-app/shared"),a=require("lodash.clonedeep"),i=require("unstorage"),r=require("object-path");function o(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var n=o(t),l=o(a),c=o(r);const h=i.createStorage();class d{constructor(){this.eventListeners={}}dispatchEvent(e,t){const s=this.eventListeners[e];s&&s.forEach((e=>{e(t)}))}on(e,t){(this.eventListeners[e]=this.eventListeners[e]||[]).push(t)}off(e,t){const s=this.eventListeners[e];if(!s)return;const a=s.indexOf(t);-1!==a&&s.splice(a,1)}}class u{constructor(t){this.id=e.nanoid(5),this.engine=t,this.options=this.engine.options,this.browser=this.engine.browser,this.settings=t.workflow.settings,this.pages=[],this.loopList={},this.repeatedTasks={},this.preloadScripts=[],this.windowId=null,this.currentBlock=null,this.childWorkflowId=null,this.activeTab={url:"",frameId:0,frames:{},groupId:null,id:t.options?.tabId}}init({blockId:e,prevBlockData:t,state:s}){s&&Object.keys(s).forEach((e=>{this[e]=s[e]}));const a=this.engine.blocks[e];this.executeBlock(a,t)}addDataToColumn(e,t){if(Array.isArray(e))return void e.forEach((e=>{s.isObject(e)&&Object.entries(e).forEach((([e,t])=>{this.addDataToColumn(e,t)}))}));const a=(this.engine.columns[e]?e:this.engine.columnsId[e])||"column",i=this.engine.columns[a],r=i.name||"column",o=s.convertData(t,i.type);s.objectHasKey(this.engine.referenceData.table,i.index)?this.engine.referenceData.table[i.index][r]=o:this.engine.referenceData.table.push({[r]:o}),i.index+=1}setVariable(e,t){this.engine.referenceData.variables[e]=t}executeNextBlocks(e,t){e.forEach((({node:e},s)=>{if(0===s)this.executeBlock(this.engine.blocks[e],t);else{const s=l.default({windowId:this.windowId,loopList:this.loopList,activeTab:this.activeTab,currentBlock:this.currentBlock,repeatedTasks:this.repeatedTasks,preloadScripts:this.preloadScripts});this.engine.addWorker({state:s,prevBlockData:t,blockId:e})}}))}async executeBlock(e,t,a){const i=await this.engine.states.get(this.engine.id);if(!i||i.isDestroyed){if(this.engine.isDestroyed)return;return void await this.engine.destroy("stopped")}const r=this.currentBlock;this.currentBlock=e,a||await this.engine.updateState({activeTabUrl:this.activeTab.url,childWorkflowId:this.childWorkflowId});const o=this.engine.blocksHandler[s.toCamelCase(e.name)],n=o||"interaction"!==s.blocks[e.name].category?o:this.engine.blocksHandler.interactionBlock;if(!n)return void this.engine.destroy("stopped",`${e.name} doesn't have handler`);const l={prevBlockData:t,...this.engine.referenceData,activeTabUrl:this.activeTab.url},h=function({block:e,refKeys:t,data:a}){if(!t||0===t.length)return e;const i=JSON.parse(JSON.stringify(e)),r=e=>{i.replacedValue||(i.replacedValue={}),i.replacedValue={...i.replacedValue,...e}};return t.forEach((e=>{const t=c.default.get(i.data,e);if(t)if(Array.isArray(t))t.forEach(((t,o)=>{const n=s.mustacheReplacer(t,a);r(n.list),c.default.set(i.data,`${e}.${o}`,n.value)}));else if("string"==typeof t){const o=s.mustacheReplacer(t,a);r(o.list),c.default.set(i.data,e,o.value)}})),i}({block:e,data:l,refKeys:a||e.data.disableBlock?null:s.blocks[e.name].refDataKeys}),d=this.settings?.blockDelay||0,u=Date.now(),p=(s,a={})=>{this.engine.addLogHistory({prevBlockData:t,type:s,name:e.name,workerId:this.id,description:e.data.description,replacedValue:h.replacedValue,duration:Math.round(Date.now()-u),...a})};try{let a;e.data.disableBlock?a={data:"",nextBlockId:s.getBlockConnection(e)}:(a=await n.call(this,h,{refData:l,prevBlock:r,prevBlockData:t}),a.replacedValue&&(h.replacedValue=a.replacedValue),p(a.status||"success",{logId:a.logId}));let i=null;i="string"==typeof a.nextBlockId?[{node:a.nextBlockId}]:a.nextBlockId.connections,i.length>0&&!a.destroyWorker?setTimeout((()=>{this.executeNextBlocks(i,a.data)}),d):this.engine.destroyWorker(this.id)}catch(a){console.error(a);const{onError:i}=h.data;if(i&&i.enable){if(i.retry&&i.retryTimes)return await s.sleep(1e3*i.retryInterval),i.retryTimes-=1,void await this.executeBlock(h,t,!0);const a=s.getBlockConnection(e,"continue"===i.toDo?1:2);if("error"!==i.toDo&&a.connections)return void this.executeNextBlocks(a.connections,t)}p("error",{message:a.message,...a.data||{}});const{onError:r}=this.settings,o=a.nextBlockId?.connections;if("keep-running"===r&&o)setTimeout((()=>{this.executeNextBlocks(o,a.data||"")}),d);else if("restart-workflow"!==r||this.parentWorkflow)this.engine.destroy("error",a.message);else{if(this.engine.restartCount>=(this.settings.restartTimes??3))return void this.engine.destroy();this.reset();const e=Object.values(this.engine.blocks).find((({name:e})=>"trigger"===e));this.executeBlock(e),this.engine.restartCount+=1}}}reset(){this.loopList={},this.repeatedTasks={},this.windowId=null,this.currentBlock=null,this.childWorkflowId=null,this.engine.history=[],this.engine.preloadScripts=[],this.engine.columns={column:{index:0,name:"column",type:"any"}},this.activeTab={url:"",frameId:0,frames:{},groupId:null,id:this.options?.tabId},this.engine.referenceData={table:[],loopData:{},workflow:{},googleSheets:{},variables:this.engine.options.variables,globalData:this.engine.referenceData.globalData}}get activePage(){return"number"!=typeof this.activeTab.id||0===this.pages.length?null:this.pages[this.activeTab.id]}}class p extends d{constructor(t,{states:a,logger:i,blocksHandler:r,browser:o,parentWorkflow:l,options:c,storage:d=h}={}){super(),this.id=e.nanoid(),this.states=a,this.logger=i,this.browser=o,this.storage=d,this.workflow=t,this.blocksHandler=r,this.parentWorkflow=l,this.saveLog=t.settings?.saveLog??!0,this.restartCount=0,this.triggerBlock=null,this.isDestroyed=!1,this.isUsingProxy=!1,this.workers=new Map,this.waitConnections={},this.blocks={},this.history=[],this.columnsId={},this.historyCtxData={},this.eventListeners={},this.columns={column:{index:0,type:"any",name:this.workflow.settings?.defaultColumnName||"column"}};let u={},{globalData:p}=t;c&&c?.data&&(p=c.data.globalData,u=s.isObject(c.data.variables)?c?.data.variables:{},c.data={globalData:p,variables:u}),this.options={exportPath:n.default.homedir(),...c||{}},this.referenceData={variables:u,table:[],loopData:{},workflow:{},googleSheets:{},globalData:s.parseJSON(p,p)},this.onWorkflowStopped=e=>{this.id!==e||this.isDestroyed||this.stop()}}init(){if(this.workflow.isDisabled)return;if(!this.blocksHandler)throw new Error("Doesn't have blocks handler");if(!this.states)throw new Error(`"${this.workflow.name}" workflow doesn't have states`);const{drawflow:e}=this.workflow,t=s.parseJSON(e,e)?.drawflow?.Home.data;if(!t)throw new Error(`${this.workflow.name} doesn't have blocks`);const a=Object.values(t).find((({name:e})=>"trigger"===e));if(!a)throw new Error(`${this.workflow.name} doesn't have a trigger block`);this.workflow.table.forEach((({name:e,type:t,id:s})=>{const a=s||e;this.columnsId[e]=a,this.columns[a]={index:0,name:e,type:t}})),this.blocks=t,this.startedTimestamp=Date.now(),this.workflow.table=columns,this.states.on("stop",this.onWorkflowStopped),this.states.add(this.id,{state:this.state,workflowId:this.workflow.id,parentState:this.parentWorkflow}).then((()=>{this.addWorker({blockId:a.id})}))}async updateState(e){const t={...this.state,...e,tabIds:[],currentBlock:[]};this.workers.forEach((e=>{t.tabIds.push(e.activeTab.id),t.currentBlock.push(e.currentBlock)})),await this.states.update(this.id,{state:t}),this.dispatchEvent("update",{state:t})}addWorker(e){const t=new u(this);t.init(e),this.workers.set(t.id,t)}addLogHistory(t){if(!this.saveLog&&(this.history.length>=1001||"blocks-group"===t.name)&&"error"!==t.type)return;const a=e.nanoid();if(t.id=a,t.replacedValue||s.blocks[t.name]?.refDataKeys&&this.saveLog){const{activeTabUrl:e,variables:s,loopData:i,prevBlockData:r}=l.default(this.referenceData);this.historyCtxData[a]={referenceData:{loopData:i,variables:s,activeTabUrl:e,prevBlockData:r},replacedValue:t.replacedValue},delete t.replacedValue}this.history.push(t)}async stop(){this.childWorkflowId&&await this.states.stop(this.childWorkflowId),await this.destroy("stopped")}destroyWorker(e){this.workers.delete(e),0===this.workers.size&&(this.addLogHistory({type:"finish",name:"finish"}),this.dispatchEvent("finish"),this.destroy("success"))}async destroy(e,t){if(this.isDestroyed)return;this.workers.clear();const s=Date.now();if(!this.workflow.isTesting){const{name:a,id:i}=this.workflow;await this.logger.add({name:a,status:e,message:t,id:this.id,workflowId:i,history:this.saveLog?this.history:[],endedAt:s,parentLog:this.parentWorkflow,startedAt:this.startedTimestamp,data:{table:this.referenceData.table,variables:this.referenceData.variables}})}this.states.off("stop",this.onWorkflowStopped),await this.states.delete(this.id),this.dispatchEvent("destroyed",{status:e,message:t,id:this.id,currentBlock:this.currentBlock,logsCtxData:this.historyCtxData,referenceData:this.referenceData}),this.isDestroyed=!0,this.eventListeners={}}get state(){const e={name:this.workflow.name,icon:this.workflow.icon};return["columns","referenceData","startedTimestamp"].forEach((t=>{e[t]=this[t]})),e}}class f extends d{constructor({storage:e=h,key:t="workflowState"}={}){super(),this.key=t,this.storage=e,this.cache=null}async _updater(e,t){try{const s=e(await this.get());return await this.storage.setItem(this.key,s),t&&this.dispatchEvent(t.name,t.params),s}catch(e){return console.error(e),[]}}async get(e){try{let t=this.cache??(await this.storage.getItem(this.key)||{});return Array.isArray(t)&&(t={},await this.storage.setItem(this.key,{})),"function"==typeof e?t=Object.values(t).find(e):e?t=t[e]:this.cache=t,t}catch(e){return console.error(e),null}}add(e,t={}){return this._updater((s=>(s[e]={id:e,isPaused:!1,isDestroyed:!1,...t},s)))}async stop(e){return await this.update(e,{isDestroyed:!0}),this.dispatchEvent("stop",e),e}update(e,t={}){const s={name:"update",params:{id:e,data:t}};return this._updater((s=>(s[e]&&(s[e]={...s[e],...t}),s)),s)}delete(e){const t={name:"delete",params:e};return this._updater((t=>(delete t[e],t)),t)}}class k extends d{constructor({storage:e=h,key:t="logs"}={}){super(),this.key=t,this.storage=e}async add(e){const t=await this.storage.getItem(this.key)||[];t.unshift(e),await this.storage.setItem(this.key,t)}}exports.WorkflowEngine=p,exports.WorkflowLogger=k,exports.WorkflowStates=f,exports.executeWorkflow=function(e,{browser:t,blocksHandler:s,options:a}){const i=new f,r=new k;return new p(e,{states:i,logger:r,browser:t,blocksHandler:s,options:a||{}})};

@@ -1,1 +0,1 @@

import{nanoid as t}from"nanoid";import e from"os";import{mustacheReplacer as s,isObject as i,convertData as a,objectHasKey as o,toCamelCase as r,blocks as n,getBlockConnection as l,sleep as h,parseJSON as c}from"@automa/shared";import d from"lodash.clonedeep";import{createStorage as u}from"unstorage";import p from"object-path";const f=u();class g{constructor(){this.eventListeners={}}dispatchEvent(t,e){const s=this.eventListeners[t];s&&s.forEach((t=>{t(e)}))}on(t,e){(this.eventListeners[t]=this.eventListeners[t]||[]).push(e)}off(t,e){const s=this.eventListeners[t];if(!s)return;const i=s.indexOf(e);-1!==i&&s.splice(i,1)}}class k{constructor(e){this.id=t(5),this.engine=e,this.options=this.engine.options,this.browser=this.engine.browser,this.settings=e.workflow.settings,this.pages=[],this.loopList={},this.repeatedTasks={},this.preloadScripts=[],this.windowId=null,this.currentBlock=null,this.childWorkflowId=null,this.activeTab={url:"",frameId:0,frames:{},groupId:null,id:e.options?.tabId}}init({blockId:t,prevBlockData:e,state:s}){s&&Object.keys(s).forEach((t=>{this[t]=s[t]}));const i=this.engine.blocks[t];this.executeBlock(i,e)}addDataToColumn(t,e){if(Array.isArray(t))return void t.forEach((t=>{i(t)&&Object.entries(t).forEach((([t,e])=>{this.addDataToColumn(t,e)}))}));const s=(this.engine.columns[t]?t:this.engine.columnsId[t])||"column",r=this.engine.columns[s],n=r.name||"column",l=a(e,r.type);o(this.engine.referenceData.table,r.index)?this.engine.referenceData.table[r.index][n]=l:this.engine.referenceData.table.push({[n]:l}),r.index+=1}setVariable(t,e){this.engine.referenceData.variables[t]=e}executeNextBlocks(t,e){t.forEach((({node:t},s)=>{if(0===s)this.executeBlock(this.engine.blocks[t],e);else{const s=d({windowId:this.windowId,loopList:this.loopList,activeTab:this.activeTab,currentBlock:this.currentBlock,repeatedTasks:this.repeatedTasks,preloadScripts:this.preloadScripts});this.engine.addWorker({state:s,prevBlockData:e,blockId:t})}}))}async executeBlock(t,e,i){const a=await this.engine.states.get(this.engine.id);if(!a||a.isDestroyed){if(this.engine.isDestroyed)return;return void await this.engine.destroy("stopped")}const o=this.currentBlock;this.currentBlock=t,i||await this.engine.updateState({activeTabUrl:this.activeTab.url,childWorkflowId:this.childWorkflowId});const c=this.engine.blocksHandler[r(t.name)],d=c||"interaction"!==n[t.name].category?c:this.engine.blocksHandler.interactionBlock;if(!d)return void this.engine.destroy("stopped",`${t.name} doesn't have handler`);const u={prevBlockData:e,...this.engine.referenceData,activeTabUrl:this.activeTab.url},f=function({block:t,refKeys:e,data:i}){if(!e||0===e.length)return t;const a=JSON.parse(JSON.stringify(t)),o=t=>{a.replacedValue||(a.replacedValue={}),a.replacedValue={...a.replacedValue,...t}};return e.forEach((t=>{const e=p.get(a.data,t);if(e)if(Array.isArray(e))e.forEach(((e,r)=>{const n=s(e,i);o(n.list),p.set(a.data,`${t}.${r}`,n.value)}));else if("string"==typeof e){const r=s(e,i);o(r.list),p.set(a.data,t,r.value)}})),a}({block:t,data:u,refKeys:i||t.data.disableBlock?null:n[t.name].refDataKeys}),g=this.settings?.blockDelay||0,k=Date.now(),w=(s,i={})=>{this.engine.addLogHistory({prevBlockData:e,type:s,name:t.name,workerId:this.id,description:t.data.description,replacedValue:f.replacedValue,duration:Math.round(Date.now()-k),...i})};try{let s;t.data.disableBlock?s={data:"",nextBlockId:l(t)}:(s=await d.call(this,f,{refData:u,prevBlock:o,prevBlockData:e}),s.replacedValue&&(f.replacedValue=s.replacedValue),w(s.status||"success",{logId:s.logId}));let i=null;i="string"==typeof s.nextBlockId?[{node:s.nextBlockId}]:s.nextBlockId.connections,i.length>0&&!s.destroyWorker?setTimeout((()=>{this.executeNextBlocks(i,s.data)}),g):this.engine.destroyWorker(this.id)}catch(s){console.error(s);const{onError:i}=f.data;if(i&&i.enable){if(i.retry&&i.retryTimes)return await h(1e3*i.retryInterval),i.retryTimes-=1,void await this.executeBlock(f,e,!0);const s=l(t,"continue"===i.toDo?1:2);if("error"!==i.toDo&&s.connections)return void this.executeNextBlocks(s.connections,e)}w("error",{message:s.message,...s.data||{}});const{onError:a}=this.settings,o=s.nextBlockId?.connections;if("keep-running"===a&&o)setTimeout((()=>{this.executeNextBlocks(o,s.data||"")}),g);else if("restart-workflow"!==a||this.parentWorkflow)this.engine.destroy("error",s.message);else{if(this.engine.restartCount>=(this.settings.restartTimes??3))return void this.engine.destroy();this.reset();const t=Object.values(this.engine.blocks).find((({name:t})=>"trigger"===t));this.executeBlock(t),this.engine.restartCount+=1}}}reset(){this.loopList={},this.repeatedTasks={},this.windowId=null,this.currentBlock=null,this.childWorkflowId=null,this.engine.history=[],this.engine.preloadScripts=[],this.engine.columns={column:{index:0,name:"column",type:"any"}},this.activeTab={url:"",frameId:0,frames:{},groupId:null,id:this.options?.tabId},this.engine.referenceData={table:[],loopData:{},workflow:{},googleSheets:{},variables:this.engine.options.variables,globalData:this.engine.referenceData.globalData}}get activePage(){return"number"!=typeof this.activeTab.id||0===this.pages.length?null:this.pages[this.activeTab.id]}}class w extends g{constructor(s,{states:a,logger:o,blocksHandler:r,browser:n,parentWorkflow:l,options:h,storage:d=f}={}){super(),this.id=t(),this.states=a,this.logger=o,this.browser=n,this.storage=d,this.workflow=s,this.blocksHandler=r,this.parentWorkflow=l,this.saveLog=s.settings?.saveLog??!0,this.restartCount=0,this.triggerBlock=null,this.isDestroyed=!1,this.isUsingProxy=!1,this.workers=new Map,this.waitConnections={},this.blocks={},this.history=[],this.columnsId={},this.historyCtxData={},this.eventListeners={},this.columns={column:{index:0,type:"any",name:this.workflow.settings?.defaultColumnName||"column"}};let u={},{globalData:p}=s;h&&h?.data&&(p=h.data.globalData,u=i(h.data.variables)?h?.data.variables:{},h.data={globalData:p,variables:u}),this.options={exportPath:e.homedir(),...h||{}},this.referenceData={variables:u,table:[],loopData:{},workflow:{},googleSheets:{},globalData:c(p,p)},this.onWorkflowStopped=t=>{this.id!==t||this.isDestroyed||this.stop()}}init(){if(this.workflow.isDisabled)return;if(!this.blocksHandler)throw new Error("Doesn't have blocks handler");if(!this.states)throw new Error(`"${this.workflow.name}" workflow doesn't have states`);const{drawflow:t}=this.workflow,e=c(t,t)?.drawflow?.Home.data;if(!e)throw new Error(`${this.workflow.name} doesn't have blocks`);const s=Object.values(e).find((({name:t})=>"trigger"===t));if(!s)throw new Error(`${this.workflow.name} doesn't have a trigger block`);this.workflow.table.forEach((({name:t,type:e,id:s})=>{const i=s||t;this.columnsId[t]=i,this.columns[i]={index:0,name:t,type:e}})),this.blocks=e,this.startedTimestamp=Date.now(),this.workflow.table=columns,this.states.on("stop",this.onWorkflowStopped),this.states.add(this.id,{state:this.state,workflowId:this.workflow.id,parentState:this.parentWorkflow}).then((()=>{this.addWorker({blockId:s.id})}))}async updateState(t){const e={...this.state,...t,tabIds:[],currentBlock:[]};this.workers.forEach((t=>{e.tabIds.push(t.activeTab.id),e.currentBlock.push(t.currentBlock)})),await this.states.update(this.id,{state:e}),this.dispatchEvent("update",{state:e})}addWorker(t){const e=new k(this);e.init(t),this.workers.set(e.id,e)}addLogHistory(e){if(!this.saveLog&&(this.history.length>=1001||"blocks-group"===e.name)&&"error"!==e.type)return;const s=t();if(e.id=s,e.replacedValue||n[e.name]?.refDataKeys&&this.saveLog){const{activeTabUrl:t,variables:i,loopData:a,prevBlockData:o}=d(this.referenceData);this.historyCtxData[s]={referenceData:{loopData:a,variables:i,activeTabUrl:t,prevBlockData:o},replacedValue:e.replacedValue},delete e.replacedValue}this.history.push(e)}async stop(){this.childWorkflowId&&await this.states.stop(this.childWorkflowId),await this.destroy("stopped")}destroyWorker(t){this.workers.delete(t),0===this.workers.size&&(this.addLogHistory({type:"finish",name:"finish"}),this.dispatchEvent("finish"),this.destroy("success"))}async destroy(t,e){if(this.isDestroyed)return;this.workers.clear();const s=Date.now();if(!this.workflow.isTesting){const{name:i,id:a}=this.workflow;await this.logger.add({name:i,status:t,message:e,id:this.id,workflowId:a,history:this.saveLog?this.history:[],endedAt:s,parentLog:this.parentWorkflow,startedAt:this.startedTimestamp,data:{table:this.referenceData.table,variables:this.referenceData.variables}})}this.states.off("stop",this.onWorkflowStopped),await this.states.delete(this.id),this.dispatchEvent("destroyed",{status:t,message:e,id:this.id,currentBlock:this.currentBlock,logsCtxData:this.historyCtxData,referenceData:this.referenceData}),this.isDestroyed=!0,this.eventListeners={}}get state(){const t={name:this.workflow.name,icon:this.workflow.icon};return["columns","referenceData","startedTimestamp"].forEach((e=>{t[e]=this[e]})),t}}class m extends g{constructor({storage:t=f,key:e="workflowState"}={}){super(),this.key=e,this.storage=t,this.cache=null}async _updater(t,e){try{const s=t(await this.get());return await this.storage.setItem(this.key,s),e&&this.dispatchEvent(e.name,e.params),s}catch(t){return console.error(t),[]}}async get(t){try{let e=this.cache??(await this.storage.getItem(this.key)||{});return Array.isArray(e)&&(e={},await this.storage.setItem(this.key,{})),"function"==typeof t?e=Object.values(e).find(t):t?e=e[t]:this.cache=e,e}catch(t){return console.error(t),null}}add(t,e={}){return this._updater((s=>(s[t]={id:t,isPaused:!1,isDestroyed:!1,...e},s)))}async stop(t){return await this.update(t,{isDestroyed:!0}),this.dispatchEvent("stop",t),t}update(t,e={}){const s={name:"update",params:{id:t,data:e}};return this._updater((s=>(s[t]&&(s[t]={...s[t],...e}),s)),s)}delete(t){const e={name:"delete",params:t};return this._updater((e=>(delete e[t],e)),e)}}class y extends g{constructor({storage:t=f,key:e="logs"}={}){super(),this.key=e,this.storage=t}async add(t){const e=await this.storage.getItem(this.key)||[];e.unshift(t),await this.storage.setItem(this.key,e)}}function b(t,{browser:e,blocksHandler:s,options:i}){const a=new m,o=new y;return new w(t,{states:a,logger:o,browser:e,blocksHandler:s,options:i||{}})}export{w as WorkflowEngine,y as WorkflowLogger,m as WorkflowStates,b as executeWorkflow};
import{nanoid as t}from"nanoid";import e from"os";import{mustacheReplacer as s,isObject as i,convertData as a,objectHasKey as o,toCamelCase as r,blocks as n,getBlockConnection as l,sleep as h,parseJSON as c}from"@automa-app/shared";import d from"lodash.clonedeep";import{createStorage as u}from"unstorage";import p from"object-path";const f=u();class g{constructor(){this.eventListeners={}}dispatchEvent(t,e){const s=this.eventListeners[t];s&&s.forEach((t=>{t(e)}))}on(t,e){(this.eventListeners[t]=this.eventListeners[t]||[]).push(e)}off(t,e){const s=this.eventListeners[t];if(!s)return;const i=s.indexOf(e);-1!==i&&s.splice(i,1)}}class k{constructor(e){this.id=t(5),this.engine=e,this.options=this.engine.options,this.browser=this.engine.browser,this.settings=e.workflow.settings,this.pages=[],this.loopList={},this.repeatedTasks={},this.preloadScripts=[],this.windowId=null,this.currentBlock=null,this.childWorkflowId=null,this.activeTab={url:"",frameId:0,frames:{},groupId:null,id:e.options?.tabId}}init({blockId:t,prevBlockData:e,state:s}){s&&Object.keys(s).forEach((t=>{this[t]=s[t]}));const i=this.engine.blocks[t];this.executeBlock(i,e)}addDataToColumn(t,e){if(Array.isArray(t))return void t.forEach((t=>{i(t)&&Object.entries(t).forEach((([t,e])=>{this.addDataToColumn(t,e)}))}));const s=(this.engine.columns[t]?t:this.engine.columnsId[t])||"column",r=this.engine.columns[s],n=r.name||"column",l=a(e,r.type);o(this.engine.referenceData.table,r.index)?this.engine.referenceData.table[r.index][n]=l:this.engine.referenceData.table.push({[n]:l}),r.index+=1}setVariable(t,e){this.engine.referenceData.variables[t]=e}executeNextBlocks(t,e){t.forEach((({node:t},s)=>{if(0===s)this.executeBlock(this.engine.blocks[t],e);else{const s=d({windowId:this.windowId,loopList:this.loopList,activeTab:this.activeTab,currentBlock:this.currentBlock,repeatedTasks:this.repeatedTasks,preloadScripts:this.preloadScripts});this.engine.addWorker({state:s,prevBlockData:e,blockId:t})}}))}async executeBlock(t,e,i){const a=await this.engine.states.get(this.engine.id);if(!a||a.isDestroyed){if(this.engine.isDestroyed)return;return void await this.engine.destroy("stopped")}const o=this.currentBlock;this.currentBlock=t,i||await this.engine.updateState({activeTabUrl:this.activeTab.url,childWorkflowId:this.childWorkflowId});const c=this.engine.blocksHandler[r(t.name)],d=c||"interaction"!==n[t.name].category?c:this.engine.blocksHandler.interactionBlock;if(!d)return void this.engine.destroy("stopped",`${t.name} doesn't have handler`);const u={prevBlockData:e,...this.engine.referenceData,activeTabUrl:this.activeTab.url},f=function({block:t,refKeys:e,data:i}){if(!e||0===e.length)return t;const a=JSON.parse(JSON.stringify(t)),o=t=>{a.replacedValue||(a.replacedValue={}),a.replacedValue={...a.replacedValue,...t}};return e.forEach((t=>{const e=p.get(a.data,t);if(e)if(Array.isArray(e))e.forEach(((e,r)=>{const n=s(e,i);o(n.list),p.set(a.data,`${t}.${r}`,n.value)}));else if("string"==typeof e){const r=s(e,i);o(r.list),p.set(a.data,t,r.value)}})),a}({block:t,data:u,refKeys:i||t.data.disableBlock?null:n[t.name].refDataKeys}),g=this.settings?.blockDelay||0,k=Date.now(),w=(s,i={})=>{this.engine.addLogHistory({prevBlockData:e,type:s,name:t.name,workerId:this.id,description:t.data.description,replacedValue:f.replacedValue,duration:Math.round(Date.now()-k),...i})};try{let s;t.data.disableBlock?s={data:"",nextBlockId:l(t)}:(s=await d.call(this,f,{refData:u,prevBlock:o,prevBlockData:e}),s.replacedValue&&(f.replacedValue=s.replacedValue),w(s.status||"success",{logId:s.logId}));let i=null;i="string"==typeof s.nextBlockId?[{node:s.nextBlockId}]:s.nextBlockId.connections,i.length>0&&!s.destroyWorker?setTimeout((()=>{this.executeNextBlocks(i,s.data)}),g):this.engine.destroyWorker(this.id)}catch(s){console.error(s);const{onError:i}=f.data;if(i&&i.enable){if(i.retry&&i.retryTimes)return await h(1e3*i.retryInterval),i.retryTimes-=1,void await this.executeBlock(f,e,!0);const s=l(t,"continue"===i.toDo?1:2);if("error"!==i.toDo&&s.connections)return void this.executeNextBlocks(s.connections,e)}w("error",{message:s.message,...s.data||{}});const{onError:a}=this.settings,o=s.nextBlockId?.connections;if("keep-running"===a&&o)setTimeout((()=>{this.executeNextBlocks(o,s.data||"")}),g);else if("restart-workflow"!==a||this.parentWorkflow)this.engine.destroy("error",s.message);else{if(this.engine.restartCount>=(this.settings.restartTimes??3))return void this.engine.destroy();this.reset();const t=Object.values(this.engine.blocks).find((({name:t})=>"trigger"===t));this.executeBlock(t),this.engine.restartCount+=1}}}reset(){this.loopList={},this.repeatedTasks={},this.windowId=null,this.currentBlock=null,this.childWorkflowId=null,this.engine.history=[],this.engine.preloadScripts=[],this.engine.columns={column:{index:0,name:"column",type:"any"}},this.activeTab={url:"",frameId:0,frames:{},groupId:null,id:this.options?.tabId},this.engine.referenceData={table:[],loopData:{},workflow:{},googleSheets:{},variables:this.engine.options.variables,globalData:this.engine.referenceData.globalData}}get activePage(){return"number"!=typeof this.activeTab.id||0===this.pages.length?null:this.pages[this.activeTab.id]}}class w extends g{constructor(s,{states:a,logger:o,blocksHandler:r,browser:n,parentWorkflow:l,options:h,storage:d=f}={}){super(),this.id=t(),this.states=a,this.logger=o,this.browser=n,this.storage=d,this.workflow=s,this.blocksHandler=r,this.parentWorkflow=l,this.saveLog=s.settings?.saveLog??!0,this.restartCount=0,this.triggerBlock=null,this.isDestroyed=!1,this.isUsingProxy=!1,this.workers=new Map,this.waitConnections={},this.blocks={},this.history=[],this.columnsId={},this.historyCtxData={},this.eventListeners={},this.columns={column:{index:0,type:"any",name:this.workflow.settings?.defaultColumnName||"column"}};let u={},{globalData:p}=s;h&&h?.data&&(p=h.data.globalData,u=i(h.data.variables)?h?.data.variables:{},h.data={globalData:p,variables:u}),this.options={exportPath:e.homedir(),...h||{}},this.referenceData={variables:u,table:[],loopData:{},workflow:{},googleSheets:{},globalData:c(p,p)},this.onWorkflowStopped=t=>{this.id!==t||this.isDestroyed||this.stop()}}init(){if(this.workflow.isDisabled)return;if(!this.blocksHandler)throw new Error("Doesn't have blocks handler");if(!this.states)throw new Error(`"${this.workflow.name}" workflow doesn't have states`);const{drawflow:t}=this.workflow,e=c(t,t)?.drawflow?.Home.data;if(!e)throw new Error(`${this.workflow.name} doesn't have blocks`);const s=Object.values(e).find((({name:t})=>"trigger"===t));if(!s)throw new Error(`${this.workflow.name} doesn't have a trigger block`);this.workflow.table.forEach((({name:t,type:e,id:s})=>{const i=s||t;this.columnsId[t]=i,this.columns[i]={index:0,name:t,type:e}})),this.blocks=e,this.startedTimestamp=Date.now(),this.workflow.table=columns,this.states.on("stop",this.onWorkflowStopped),this.states.add(this.id,{state:this.state,workflowId:this.workflow.id,parentState:this.parentWorkflow}).then((()=>{this.addWorker({blockId:s.id})}))}async updateState(t){const e={...this.state,...t,tabIds:[],currentBlock:[]};this.workers.forEach((t=>{e.tabIds.push(t.activeTab.id),e.currentBlock.push(t.currentBlock)})),await this.states.update(this.id,{state:e}),this.dispatchEvent("update",{state:e})}addWorker(t){const e=new k(this);e.init(t),this.workers.set(e.id,e)}addLogHistory(e){if(!this.saveLog&&(this.history.length>=1001||"blocks-group"===e.name)&&"error"!==e.type)return;const s=t();if(e.id=s,e.replacedValue||n[e.name]?.refDataKeys&&this.saveLog){const{activeTabUrl:t,variables:i,loopData:a,prevBlockData:o}=d(this.referenceData);this.historyCtxData[s]={referenceData:{loopData:a,variables:i,activeTabUrl:t,prevBlockData:o},replacedValue:e.replacedValue},delete e.replacedValue}this.history.push(e)}async stop(){this.childWorkflowId&&await this.states.stop(this.childWorkflowId),await this.destroy("stopped")}destroyWorker(t){this.workers.delete(t),0===this.workers.size&&(this.addLogHistory({type:"finish",name:"finish"}),this.dispatchEvent("finish"),this.destroy("success"))}async destroy(t,e){if(this.isDestroyed)return;this.workers.clear();const s=Date.now();if(!this.workflow.isTesting){const{name:i,id:a}=this.workflow;await this.logger.add({name:i,status:t,message:e,id:this.id,workflowId:a,history:this.saveLog?this.history:[],endedAt:s,parentLog:this.parentWorkflow,startedAt:this.startedTimestamp,data:{table:this.referenceData.table,variables:this.referenceData.variables}})}this.states.off("stop",this.onWorkflowStopped),await this.states.delete(this.id),this.dispatchEvent("destroyed",{status:t,message:e,id:this.id,currentBlock:this.currentBlock,logsCtxData:this.historyCtxData,referenceData:this.referenceData}),this.isDestroyed=!0,this.eventListeners={}}get state(){const t={name:this.workflow.name,icon:this.workflow.icon};return["columns","referenceData","startedTimestamp"].forEach((e=>{t[e]=this[e]})),t}}class m extends g{constructor({storage:t=f,key:e="workflowState"}={}){super(),this.key=e,this.storage=t,this.cache=null}async _updater(t,e){try{const s=t(await this.get());return await this.storage.setItem(this.key,s),e&&this.dispatchEvent(e.name,e.params),s}catch(t){return console.error(t),[]}}async get(t){try{let e=this.cache??(await this.storage.getItem(this.key)||{});return Array.isArray(e)&&(e={},await this.storage.setItem(this.key,{})),"function"==typeof t?e=Object.values(e).find(t):t?e=e[t]:this.cache=e,e}catch(t){return console.error(t),null}}add(t,e={}){return this._updater((s=>(s[t]={id:t,isPaused:!1,isDestroyed:!1,...e},s)))}async stop(t){return await this.update(t,{isDestroyed:!0}),this.dispatchEvent("stop",t),t}update(t,e={}){const s={name:"update",params:{id:t,data:e}};return this._updater((s=>(s[t]&&(s[t]={...s[t],...e}),s)),s)}delete(t){const e={name:"delete",params:t};return this._updater((e=>(delete e[t],e)),e)}}class y extends g{constructor({storage:t=f,key:e="logs"}={}){super(),this.key=e,this.storage=t}async add(t){const e=await this.storage.getItem(this.key)||[];e.unshift(t),await this.storage.setItem(this.key,e)}}function b(t,{browser:e,blocksHandler:s,options:i}){const a=new m,o=new y;return new w(t,{states:a,logger:o,browser:e,blocksHandler:s,options:i||{}})}export{w as WorkflowEngine,y as WorkflowLogger,m as WorkflowStates,b as executeWorkflow};
{
"name": "@automa-app/core",
"version": "0.9.1",
"version": "0.9.3",
"license": "MIT",

@@ -5,0 +5,0 @@ "main": "dist/automa-core.cjs.js",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc