Skip to content

Commit

Permalink
feat: add workflow-engine
Browse files Browse the repository at this point in the history
  • Loading branch information
Kholid060 committed Oct 9, 2021
1 parent af70a29 commit 8410aef
Show file tree
Hide file tree
Showing 9 changed files with 245 additions and 6 deletions.
22 changes: 21 additions & 1 deletion src/background/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
import { MessageListener } from '@/utils/message';
import WorkflowEngine from '@/utils/workflow-engine';

chrome.runtime.onInstalled.addListener((details) => {
if (details.reason === chrome.runtime.OnInstalledReason.INSTALL) {
chrome.storage.set({
chrome.storage.local.set({
workflows: [],
tasks: [],
});
}
});

const message = new MessageListener('background');

message.on('workflow:execute', (workflow) => {
try {
const engine = new WorkflowEngine(workflow);
console.log('execute');
engine.init();

return true;
} catch (error) {
console.error(error);
return error;
}
});

chrome.runtime.onMessage.addListener(message.listener());
7 changes: 7 additions & 0 deletions src/content/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import browser from 'webextension-polyfill';
import { printLine } from './modules/print';

console.log('Content script works!');
console.log('Must reload extension for modifications to take effect.');

printLine("Using the 'printLine' function from the Print Module");

(() => {
browser.runtime.onConnect.addListener((a, b) => {
console.log(a, b);
});
})();
2 changes: 1 addition & 1 deletion src/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
"icons": {
"128": "icon-128.png"
},
"permissions": ["scripting", "storage", "unlimitedStorage", "tabs"],
"permissions": ["storage", "unlimitedStorage", "tabs", "activeTab", "http://*/*", "https://*/*"],
"web_accessible_resources": ["content.styles.css", "icon-128.png", "icon-34.png"]
}
17 changes: 16 additions & 1 deletion src/newtab/pages/workflows/[id].vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
} from 'vue';
import { useRoute, useRouter, onBeforeRouteLeave } from 'vue-router';
import emitter from 'tiny-emitter/instance';
import { sendMessage } from '@/utils/message';
import { debounce } from '@/utils/helper';
import { useDialog } from '@/composable/dialog';
import Workflow from '@/models/workflow';
Expand Down Expand Up @@ -107,7 +108,21 @@ function editBlock(data) {
state.blockData = data;
}
function executeWorkflow() {
console.log(editor.value);
if (editor.value.getNodesFromName('trigger').length === 0) {
/* eslint-disable-next-line */
alert("Can't find a trigger block");
return;
}
const payload = {
...workflow.value,
drawflow: editor.value.export(),
isTesting: state.isDataChanged,
};
sendMessage('workflow:execute', payload, 'background').then(() => {
console.log('the fuck');
});
}
function handleEditorDataChanged() {
state.isDataChanged = true;
Expand Down
54 changes: 54 additions & 0 deletions src/utils/blocks-handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import browser from 'webextension-polyfill';

function getBlockConnection(block, index = 1) {
const blockId = block.outputs[`output_${index}`].connections[0]?.node;

return blockId;
}

export function trigger(block) {
return new Promise((resolve) => {
const nextBlockId = getBlockConnection(block);

resolve({ nextBlockId });
});
}

export function openWebsite(block) {
return new Promise((resolve) => {
browser.tabs
.create({
active: true,
url: block.data.url,
})
.then((tab) => {
const tabListener = (tabId, changeInfo) => {
if (changeInfo.status === 'complete' && tabId === tab.id) {
browser.tabs.onUpdated.removeListener(tabListener);

browser.tabs
.executeScript(tabId, {
file: './contentScript.bundle.js',
})
.then(() => {
this.connectedTab = browser.tabs.connect(tabId, {
name: `${this.workflow.id}--${this.workflow.name.slice(
0,
10
)}`,
});
this.tabId = tabId;

resolve({ nextBlockId: getBlockConnection(block) });
});
}
};

browser.tabs.onUpdated.addListener(tabListener);
})
.catch((error) => {
console.error(error, 'nnnaa');
reject(error);
});
});
}
12 changes: 12 additions & 0 deletions src/utils/helper.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
export function toCamelCase(str) {
const result = str.replace(/(?:^\w|[A-Z]|\b\w)/g, (letter, index) => {
return index === 0 ? letter.toLowerCase() : letter.toUpperCase();
});

return result.replace(/\s+|[-]/g, '');
}

export function isObject(obj) {
return typeof obj === 'object' && object !== null;
}

export function objectHasKey(obj, key) {
return Object.prototype.hasOwnProperty.call(obj, key);
}
Expand Down
71 changes: 71 additions & 0 deletions src/utils/message.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import browser from 'webextension-polyfill';
import { objectHasKey } from './helper';

const nameBuilder = (prefix, name) => (prefix ? `${prefix}--${name}` : name);

export class MessageListener {
constructor(prefix = '') {
this.listeners = {};
this.prefix = prefix;
}

on(name, listener) {
if (objectHasKey(this.listeners, 'name')) {
console.error(`You already added ${name}`);
return;
}

this.listeners[nameBuilder(this.prefix, name)] = listener;
}

listener() {
return this.listen.bind(this);
}

listen(message, sender, sendResponse) {
try {
const listener = this.listeners[message.name];

const response =
listener && listener.call({ message, sender }, message.data, sender);

if (!response) {
// Do nothing
} else if (!(response instanceof Promise)) {
sendResponse(response);
} else {
response
.then((res) => {
sendResponse(res);
})
.catch((res) => {
sendResponse(res);
});
}
} catch (err) {
sendResponse({
error: true,
message: `Unhandled Background Error: ${String(err)}`,
});
}
}
}

export function sendMessage(name = '', data = {}, prefix = '') {
return new Promise((resolve, reject) => {
const payload = {
name: nameBuilder(prefix, name),
data,
};

browser.runtime
.sendMessage(payload)
.then((response) => {
if (response.error) reject(new Error(response.message));
else resolve(response);
})
.catch((error) => {
reject(error);
});
});
}
59 changes: 59 additions & 0 deletions src/utils/workflow-engine.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/* eslint-disable no-underscore-dangle */
import { toCamelCase } from './helper';
import * as blocksHandler from './blocks-handler';

class WorkflowEngine {
constructor(workflow) {
this.workflow = workflow;
this.blocks = {};
this.blocksArr = [];
this.data = [];
}

init() {
const drawflowData =
typeof this.workflow.drawflow === 'string'
? JSON.parse(this.workflow.drawflow || '{}')
: this.workflow.drawflow;
const blocks = drawflowData?.drawflow.Home.data;

if (!blocks) return;

const blocksArr = Object.values(blocks);
const triggerBlock = blocksArr.find(({ name }) => name === 'trigger');

if (!triggerBlock) {
console.error('A trigger block is required');
return;
}

this.blocks = blocks;
this.blocksArr = blocksArr;

this._blockHandler(triggerBlock);
}

_blockHandler(block) {
console.log(`${block.name}(${toCamelCase(block.name)}):`, block);
const handler = blocksHandler[toCamelCase(block?.name)];

if (handler) {
handler
.call(this, block)
.then((result) => {
if (result.nextBlockId) {
this._blockHandler(this.blocks[result.nextBlockId]);
} else {
console.log('Done');
}
})
.catch((error) => {
console.error(error, 'new');
});
} else {
console.error(`"${block.name}" block doesn't have a handler`);
}
}
}

export default WorkflowEngine;
7 changes: 4 additions & 3 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const options = {
contentScript: path.join(__dirname, 'src', 'content', 'index.js'),
},
chromeExtensionBoilerplate: {
notHotReload: ['contentScript', 'devtools'],
notHotReload: ['contentScript'],
},
output: {
path: path.resolve(__dirname, 'build'),
Expand All @@ -58,11 +58,12 @@ const options = {
loader: 'vue-loader',
},
{
// look for .css or .scss files
test: /\.css$/,
// in the `src` directory
use: [
MiniCssExtractPlugin.loader,
// {
// loader: 'style-loader',
// },
{
loader: 'css-loader',
},
Expand Down

0 comments on commit 8410aef

Please sign in to comment.