From 80ca4ea76eb9d0e18eb3695f79708539e4eee392 Mon Sep 17 00:00:00 2001 From: Simon Larsen Date: Thu, 16 Feb 2023 13:07:40 +0000 Subject: [PATCH] add workflow components. --- Common/Types/Workflow/ComponentID.ts | 9 +++ Common/Types/Workflow/Components/Log.ts | 3 +- Common/Types/Workflow/Components/Webhook.ts | 3 +- CommonServer/Types/Workflow/ComponentCode.ts | 49 ++++++++-------- .../Types/Workflow/Components/Index.ts | 10 ++++ CommonServer/Types/Workflow/Components/Log.ts | 35 ++++++++++++ .../Types/Workflow/Components/Schedule.ts | 56 +++++++++++++++++++ .../Types/Workflow/Components/Webhook.ts | 54 ++++++++++++++++++ 8 files changed, 191 insertions(+), 28 deletions(-) create mode 100644 Common/Types/Workflow/ComponentID.ts create mode 100644 CommonServer/Types/Workflow/Components/Index.ts create mode 100644 CommonServer/Types/Workflow/Components/Log.ts diff --git a/Common/Types/Workflow/ComponentID.ts b/Common/Types/Workflow/ComponentID.ts new file mode 100644 index 0000000000..51b7280a9c --- /dev/null +++ b/Common/Types/Workflow/ComponentID.ts @@ -0,0 +1,9 @@ +enum ComponentID { + Webhook = "webhook", + Log = "log", + Schedule="schedule" + + +} + +export default ComponentID; \ No newline at end of file diff --git a/Common/Types/Workflow/Components/Log.ts b/Common/Types/Workflow/Components/Log.ts index 6027d53852..6b0ec485a4 100644 --- a/Common/Types/Workflow/Components/Log.ts +++ b/Common/Types/Workflow/Components/Log.ts @@ -1,4 +1,5 @@ import IconProp from '../../Icon/IconProp'; +import ComponentID from '../ComponentID'; import ComponentMetadata, { ComponentInputType, ComponentType, @@ -6,7 +7,7 @@ import ComponentMetadata, { const components: Array = [ { - id: 'log', + id: ComponentID.Log, title: 'Log', category: 'Utils', description: 'Log to console what ever is passed to this component', diff --git a/Common/Types/Workflow/Components/Webhook.ts b/Common/Types/Workflow/Components/Webhook.ts index 9301b52809..c6f0b1d5a6 100644 --- a/Common/Types/Workflow/Components/Webhook.ts +++ b/Common/Types/Workflow/Components/Webhook.ts @@ -3,10 +3,11 @@ import ComponentMetadata, { ComponentInputType, ComponentType, } from './../Component'; +import ComponentID from "../ComponentID"; const components: Array = [ { - id: 'webhook', + id: ComponentID.Webhook, title: 'Webhook', category: 'Webhook', description: diff --git a/CommonServer/Types/Workflow/ComponentCode.ts b/CommonServer/Types/Workflow/ComponentCode.ts index e4f8facb6a..23484852d6 100644 --- a/CommonServer/Types/Workflow/ComponentCode.ts +++ b/CommonServer/Types/Workflow/ComponentCode.ts @@ -2,61 +2,58 @@ // import BadDataException from "Common/Types/Exception/BadDataException"; -import NotImplementedException from "Common/Types/Exception/NotImplementedException"; import { JSONObject } from "Common/Types/JSON"; import ObjectID from "Common/Types/ObjectID"; import ComponentMetadata, { Port } from "Common/Types/Workflow/Component"; import { ExpressRouter } from "../../Utils/Express"; export interface RunProps { - global: { - variables: JSONObject - }, - local: { - variables: JSONObject, - components: { - // component id. - [x: string]: { - returnValues: JSONObject - } - } - }, - workflowId: ObjectID, - workflowRunId: ObjectID + arguments: JSONObject; + workflowId: ObjectID; + workflowRunId: ObjectID; } export interface RunReturnType { returnValues: JSONObject, - executePort: Port + executePort?: Port | undefined } -export interface InitProps{ +export interface ExecuteWorkflowType { + workflowId: ObjectID, + returnValues: JSONObject, +} + +export interface InitProps { router: ExpressRouter; - runWorkflow: (workflowId: ObjectID, returnValues: JSONObject) => void; + executeWorkflow: (executeWorkflow: ExecuteWorkflowType) => Promise; + scheduleWorkflow: (executeWorkflow: ExecuteWorkflowType, scheduleAt: string) => Promise; } -export default class ComponentCode { +export default class ComponentCode { private metadata: ComponentMetadata | null = null; - public constructor(metadata: ComponentMetadata){ + public constructor(metadata: ComponentMetadata) { this.metadata = metadata; } - public getMetadata(): ComponentMetadata { - if(!this.metadata){ + public getMetadata(): ComponentMetadata { + if (!this.metadata) { throw new BadDataException("ComponentMetadata not found") } return this.metadata; } - public async init(_props: InitProps ): Promise{ - throw new NotImplementedException(); + public async init(_props: InitProps): Promise { + return await Promise.resolve() } - public async run(_props: RunProps): Promise{ - throw new NotImplementedException(); + public async run(_props: RunProps): Promise { + return await Promise.resolve({ + returnValues: {}, + port: undefined + }) } } \ No newline at end of file diff --git a/CommonServer/Types/Workflow/Components/Index.ts b/CommonServer/Types/Workflow/Components/Index.ts new file mode 100644 index 0000000000..d619912ed1 --- /dev/null +++ b/CommonServer/Types/Workflow/Components/Index.ts @@ -0,0 +1,10 @@ +import ComponentID from "Common/Types/Workflow/ComponentID"; +import WebhookTrigger from "./Webhook"; +import Log from "./Log"; +import Schedule from "./Schedule"; + +export default { + [ComponentID.Webhook]: WebhookTrigger, + [ComponentID.Log]: Log, + [ComponentID.Schedule]: Schedule +} \ No newline at end of file diff --git a/CommonServer/Types/Workflow/Components/Log.ts b/CommonServer/Types/Workflow/Components/Log.ts new file mode 100644 index 0000000000..9b02ea3be4 --- /dev/null +++ b/CommonServer/Types/Workflow/Components/Log.ts @@ -0,0 +1,35 @@ +import OneUptimeDate from "Common/Types/Date"; +import BadDataException from "Common/Types/Exception/BadDataException"; +import ComponentMetadata, { Port } from "Common/Types/Workflow/Component"; +import ComponentID from "Common/Types/Workflow/ComponentID"; +import WebhookComponents from "Common/Types/Workflow/Components/Webhook"; +import ComponentCode, { RunProps, RunReturnType } from "../ComponentCode"; + +export default class Log extends ComponentCode { + public constructor() { + + const LogComponent: ComponentMetadata | undefined = WebhookComponents.find((i: ComponentMetadata) => i.id === ComponentID.Log); + + if (!LogComponent) { + throw new BadDataException("Component not found.") + } + super(LogComponent); + } + + public override run(props: RunProps): Promise { + + const outPort: Port | undefined = this.getMetadata().outPorts.find((p)=> p.id === "out"); + + if(!outPort){ + throw new BadDataException("Out port not found"); + } + + console.log(OneUptimeDate.getCurrentDateAsFormattedString()+":"); + console.log(props.arguments["value"]); + + return Promise.resolve({ + returnValues: {}, + executePort: outPort + }); + } +} diff --git a/CommonServer/Types/Workflow/Components/Schedule.ts b/CommonServer/Types/Workflow/Components/Schedule.ts index e69de29bb2..625301d2de 100644 --- a/CommonServer/Types/Workflow/Components/Schedule.ts +++ b/CommonServer/Types/Workflow/Components/Schedule.ts @@ -0,0 +1,56 @@ +import LIMIT_MAX from "Common/Types/Database/LimitMax"; +import BadDataException from "Common/Types/Exception/BadDataException"; +import ObjectID from "Common/Types/ObjectID"; +import ComponentMetadata from "Common/Types/Workflow/Component"; +import ComponentID from "Common/Types/Workflow/ComponentID"; +import WebhookComponents from "Common/Types/Workflow/Components/Webhook"; +import Workflow from "Model/Models/Workflow"; +import WorkflowService from "../../../Services/WorkflowService"; +import QueryHelper from "../../Database/QueryHelper"; +import ComponentCode, { ExecuteWorkflowType, InitProps } from "../ComponentCode"; + +export default class WebhookTrigger extends ComponentCode { + public constructor() { + + const component: ComponentMetadata | undefined = WebhookComponents.find((i: ComponentMetadata) => i.id === ComponentID.Schedule); + + if (!component) { + throw new BadDataException("Trigger not found.") + } + super(component); + } + + public override async init(props: InitProps): Promise { + + const workflows: Array = await WorkflowService.findBy({ + query: { + triggerId: ComponentID.Schedule, + triggerArguments: QueryHelper.notNull() + }, + select:{ + _id: true, + triggerArguments: true, + }, + props: { + isRoot: true, + }, + limit: LIMIT_MAX, + skip: 0 + }); + + + // query all workflows. + for(const workflow of workflows){ + const executeWorkflow: ExecuteWorkflowType = { + workflowId: new ObjectID(workflow._id!), + returnValues: {} + }; + + if(workflow.triggerArguments && workflow.triggerArguments["schedule"]){ + await props.scheduleWorkflow(executeWorkflow, workflow.triggerArguments["schedule"] as string) + } + } + + } +} + diff --git a/CommonServer/Types/Workflow/Components/Webhook.ts b/CommonServer/Types/Workflow/Components/Webhook.ts index e69de29bb2..83c4071a6b 100644 --- a/CommonServer/Types/Workflow/Components/Webhook.ts +++ b/CommonServer/Types/Workflow/Components/Webhook.ts @@ -0,0 +1,54 @@ +import BadDataException from "Common/Types/Exception/BadDataException"; +import ObjectID from "Common/Types/ObjectID"; +import ComponentMetadata from "Common/Types/Workflow/Component"; +import ComponentID from "Common/Types/Workflow/ComponentID"; +import WebhookComponents from "Common/Types/Workflow/Components/Webhook"; +import { ExpressRequest, ExpressResponse } from "../../../Utils/Express"; +import Response from "../../../Utils/Response"; +import ComponentCode, { ExecuteWorkflowType, InitProps } from "../ComponentCode"; + +export default class WebhookTrigger extends ComponentCode { + public constructor() { + + const WebhookComponent: ComponentMetadata | undefined = WebhookComponents.find((i: ComponentMetadata) => i.id === ComponentID.Webhook); + + if (!WebhookComponent) { + throw new BadDataException("Webhook trigger not found.") + } + super(WebhookComponent); + } + + public override async init(props: InitProps): Promise { + props.router.get( + `/trigger/:workflowId`, + async (req: ExpressRequest, res: ExpressResponse) => { + await this.initTrigger(req, res, props); + } + ); + + props.router.post( + `/trigger/:workflowId`, + async (req: ExpressRequest, res: ExpressResponse) => { + await this.initTrigger(req, res, props); + } + ); + } + + public async initTrigger(req: ExpressRequest, res: ExpressResponse, props: InitProps) { + /// Run Graph. + + const executeWorkflow: ExecuteWorkflowType = { + workflowId: new ObjectID(req.params['workflowId'] as string), + returnValues: { + 'request-headers': req.headers, + 'request-params': req.query, + 'request-body': req.body + } + }; + + await props.executeWorkflow(executeWorkflow); + + Response.sendJsonObjectResponse(req, res, { status: "Scheduled" }); + } +} +