From 5c9c06abd47a1e4b7735a0841b14257595f1f532 Mon Sep 17 00:00:00 2001 From: Simon Larsen Date: Wed, 1 Mar 2023 12:11:07 +0000 Subject: [PATCH 01/11] fix json placeholder --- Common/Types/Workflow/Components/BaseModel.ts | 12 ++++++++++++ CommonUI/src/Components/CodeEditor/CodeEditor.tsx | 9 ++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Common/Types/Workflow/Components/BaseModel.ts b/Common/Types/Workflow/Components/BaseModel.ts index d01483eee0..65c0c2376c 100644 --- a/Common/Types/Workflow/Components/BaseModel.ts +++ b/Common/Types/Workflow/Components/BaseModel.ts @@ -30,6 +30,7 @@ export default class BaseModelComponent { description: `Query on ${model.singularName}`, required: true, id: 'query', + placeholder: "Example: {'columnName': 'value', ...}" }, { type: ComponentInputType.Query, @@ -37,6 +38,7 @@ export default class BaseModelComponent { description: `Select on ${model.singularName}`, required: true, id: 'select', + placeholder: "Example: {'columnName': true, ...}" }, ], returnValues: [ @@ -87,6 +89,7 @@ export default class BaseModelComponent { description: 'Please fill out this query', required: true, id: 'query', + placeholder: "Example: {'columnName': 'value', ...}" }, { type: ComponentInputType.Query, @@ -94,6 +97,7 @@ export default class BaseModelComponent { description: `Select on ${model.singularName}`, required: true, id: 'select', + placeholder: "Example: {'columnName': true, ...}" }, { type: ComponentInputType.Number, @@ -189,6 +193,7 @@ export default class BaseModelComponent { description: 'Please fill out this query', required: true, id: 'query', + placeholder: "Example: {'columnName': 'value', ...}" }, ], returnValues: [], @@ -231,6 +236,7 @@ export default class BaseModelComponent { description: 'Please fill out this query', required: true, id: 'query', + placeholder: "Example: {'columnName': 'value', ...}" }, { type: ComponentInputType.Number, @@ -314,6 +320,7 @@ export default class BaseModelComponent { arguments: [ { id: 'json', + placeholder: "Example: {'columnName': 'value', ...}", name: 'JSON Object', description: `${model.singularName} represented as JSON`, type: ComponentInputType.JSON, @@ -365,6 +372,7 @@ export default class BaseModelComponent { { id: 'json-array', name: 'JSON Array', + placeholder: "Example: [{'columnName': 'value', ...}, {...}]", description: 'List of models represented as JSON array', type: ComponentInputType.JSONArray, required: true, @@ -448,9 +456,11 @@ export default class BaseModelComponent { description: 'Please fill out this query', required: true, id: 'query', + placeholder: "Example: {'columnName': 'value', ...}" }, { id: 'data', + placeholder: "Example: {'columnName': 'value', ...}", name: 'Data (JSON Object)', description: `${model.singularName} represented as JSON`, type: ComponentInputType.JSON, @@ -497,10 +507,12 @@ export default class BaseModelComponent { description: 'Please fill out this query', required: true, id: 'query', + placeholder: "Example: {'columnName': 'value', ...}" }, { id: 'data', name: 'Data (JSON Object)', + placeholder: "Example: {'columnName': 'value', ...}", description: `${model.singularName} represented as JSON`, type: ComponentInputType.JSON, required: true, diff --git a/CommonUI/src/Components/CodeEditor/CodeEditor.tsx b/CommonUI/src/Components/CodeEditor/CodeEditor.tsx index 76bc029f51..51ee4a0b39 100644 --- a/CommonUI/src/Components/CodeEditor/CodeEditor.tsx +++ b/CommonUI/src/Components/CodeEditor/CodeEditor.tsx @@ -31,6 +31,7 @@ const CodeEditor: FunctionComponent = ( let className: string = ''; const [placeholder, setPlaceholder] = useState(''); + const [helpText, setHelpText] = useState(''); useEffect(() => { if (props.type === CodeType.Markdown) { @@ -50,7 +51,7 @@ const CodeEditor: FunctionComponent = ( } if (props.type === CodeType.JSON) { - setPlaceholder(`// ${props.placeholder}. This is in JSON.`); + setHelpText(`${props.placeholder}`); } if (props.type === CodeType.CSS) { @@ -106,6 +107,12 @@ const CodeEditor: FunctionComponent = ( props.onFocus && props.onFocus(); }} > + + {helpText &&

{helpText}

} + Date: Wed, 1 Mar 2023 13:02:31 +0000 Subject: [PATCH 02/11] add json component --- Common/Types/Workflow/ComponentID.ts | 3 + Common/Types/Workflow/Components/JSON.ts | 7 +- .../{ => BaseModel}/CreateManyBaseModel.ts | 4 +- .../{ => BaseModel}/CreateOneBaseModel.ts | 4 +- .../{ => BaseModel}/DeleteManyBaseMoidel.ts | 6 +- .../{ => BaseModel}/DeleteOneBaseModel.ts | 6 +- .../{ => BaseModel}/FindManyBaseModel.ts | 8 +- .../{ => BaseModel}/FindOneBaseModel.ts | 8 +- .../{ => BaseModel}/OnCreateBaseModel.ts | 2 +- .../{ => BaseModel}/OnDeleteBaseModel.ts | 2 +- .../{ => BaseModel}/OnTriggerBaseModel.ts | 12 +-- .../{ => BaseModel}/OnUpdateBaseModel.ts | 2 +- .../{ => BaseModel}/UpdateManyBaseModel.ts | 6 +- .../{ => BaseModel}/UpdateOneBaseModel.ts | 6 +- .../Types/Workflow/Components/Index.ts | 22 ++--- .../Workflow/Components/JSON/JsonToText.ts | 86 +++++++++++++++++ .../Workflow/Components/JSON/MergeJson.ts | 96 +++++++++++++++++++ .../Workflow/Components/JSON/TextToJson.ts | 82 ++++++++++++++++ 18 files changed, 315 insertions(+), 47 deletions(-) rename CommonServer/Types/Workflow/Components/{ => BaseModel}/CreateManyBaseModel.ts (96%) rename CommonServer/Types/Workflow/Components/{ => BaseModel}/CreateOneBaseModel.ts (96%) rename CommonServer/Types/Workflow/Components/{ => BaseModel}/DeleteManyBaseMoidel.ts (96%) rename CommonServer/Types/Workflow/Components/{ => BaseModel}/DeleteOneBaseModel.ts (95%) rename CommonServer/Types/Workflow/Components/{ => BaseModel}/FindManyBaseModel.ts (95%) rename CommonServer/Types/Workflow/Components/{ => BaseModel}/FindOneBaseModel.ts (95%) rename CommonServer/Types/Workflow/Components/{ => BaseModel}/OnCreateBaseModel.ts (83%) rename CommonServer/Types/Workflow/Components/{ => BaseModel}/OnDeleteBaseModel.ts (83%) rename CommonServer/Types/Workflow/Components/{ => BaseModel}/OnTriggerBaseModel.ts (90%) rename CommonServer/Types/Workflow/Components/{ => BaseModel}/OnUpdateBaseModel.ts (83%) rename CommonServer/Types/Workflow/Components/{ => BaseModel}/UpdateManyBaseModel.ts (96%) rename CommonServer/Types/Workflow/Components/{ => BaseModel}/UpdateOneBaseModel.ts (96%) create mode 100644 CommonServer/Types/Workflow/Components/JSON/JsonToText.ts create mode 100644 CommonServer/Types/Workflow/Components/JSON/MergeJson.ts create mode 100644 CommonServer/Types/Workflow/Components/JSON/TextToJson.ts diff --git a/Common/Types/Workflow/ComponentID.ts b/Common/Types/Workflow/ComponentID.ts index f910fbda7c..31a4d78766 100644 --- a/Common/Types/Workflow/ComponentID.ts +++ b/Common/Types/Workflow/ComponentID.ts @@ -4,6 +4,9 @@ enum ComponentID { Schedule = 'schedule', JavaScriptCode = 'javascript', Manual = 'manual', + JsonToText = 'json-to-text', + TextToJson = 'text-to-json', + MergeJson = 'merge-json' } export default ComponentID; diff --git a/Common/Types/Workflow/Components/JSON.ts b/Common/Types/Workflow/Components/JSON.ts index 033f98b063..169f2623a9 100644 --- a/Common/Types/Workflow/Components/JSON.ts +++ b/Common/Types/Workflow/Components/JSON.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: 'json-to-text', + id: ComponentID.JsonToText, title: 'JSON to Text', category: 'JSON', description: 'Converts JSON Object to Text', @@ -54,7 +55,7 @@ const components: Array = [ ], }, { - id: 'text-to-json', + id: ComponentID.TextToJson, title: 'Text to JSON', category: 'JSON', description: 'Converts Text to JSON Object', @@ -102,7 +103,7 @@ const components: Array = [ ], }, { - id: 'json-merge', + id: ComponentID.MergeJson, title: 'Merge JSON', category: 'JSON', description: 'Merge two JSON Objects into one', diff --git a/CommonServer/Types/Workflow/Components/CreateManyBaseModel.ts b/CommonServer/Types/Workflow/Components/BaseModel/CreateManyBaseModel.ts similarity index 96% rename from CommonServer/Types/Workflow/Components/CreateManyBaseModel.ts rename to CommonServer/Types/Workflow/Components/BaseModel/CreateManyBaseModel.ts index dabbfa0083..f3ea78acfc 100644 --- a/CommonServer/Types/Workflow/Components/CreateManyBaseModel.ts +++ b/CommonServer/Types/Workflow/Components/BaseModel/CreateManyBaseModel.ts @@ -1,8 +1,8 @@ import BaseModel from 'Common/Models/BaseModel'; import BadDataException from 'Common/Types/Exception/BadDataException'; import ComponentMetadata, { Port } from 'Common/Types/Workflow/Component'; -import DatabaseService from '../../../Services/DatabaseService'; -import ComponentCode, { RunOptions, RunReturnType } from '../ComponentCode'; +import DatabaseService from '../../../../Services/DatabaseService'; +import ComponentCode, { RunOptions, RunReturnType } from '../../ComponentCode'; import BaseModelComponents from 'Common/Types/Workflow/Components/BaseModel'; import Text from 'Common/Types/Text'; import { JSONObject } from 'Common/Types/JSON'; diff --git a/CommonServer/Types/Workflow/Components/CreateOneBaseModel.ts b/CommonServer/Types/Workflow/Components/BaseModel/CreateOneBaseModel.ts similarity index 96% rename from CommonServer/Types/Workflow/Components/CreateOneBaseModel.ts rename to CommonServer/Types/Workflow/Components/BaseModel/CreateOneBaseModel.ts index 0255355577..7bc088e761 100644 --- a/CommonServer/Types/Workflow/Components/CreateOneBaseModel.ts +++ b/CommonServer/Types/Workflow/Components/BaseModel/CreateOneBaseModel.ts @@ -1,8 +1,8 @@ import BaseModel from 'Common/Models/BaseModel'; import BadDataException from 'Common/Types/Exception/BadDataException'; import ComponentMetadata, { Port } from 'Common/Types/Workflow/Component'; -import DatabaseService from '../../../Services/DatabaseService'; -import ComponentCode, { RunOptions, RunReturnType } from '../ComponentCode'; +import DatabaseService from '../../../../Services/DatabaseService'; +import ComponentCode, { RunOptions, RunReturnType } from '../../ComponentCode'; import BaseModelComponents from 'Common/Types/Workflow/Components/BaseModel'; import Text from 'Common/Types/Text'; import { JSONObject } from 'Common/Types/JSON'; diff --git a/CommonServer/Types/Workflow/Components/DeleteManyBaseMoidel.ts b/CommonServer/Types/Workflow/Components/BaseModel/DeleteManyBaseMoidel.ts similarity index 96% rename from CommonServer/Types/Workflow/Components/DeleteManyBaseMoidel.ts rename to CommonServer/Types/Workflow/Components/BaseModel/DeleteManyBaseMoidel.ts index 5fd7a1bcd2..b4f6f1d7a8 100644 --- a/CommonServer/Types/Workflow/Components/DeleteManyBaseMoidel.ts +++ b/CommonServer/Types/Workflow/Components/BaseModel/DeleteManyBaseMoidel.ts @@ -1,12 +1,12 @@ import BaseModel from 'Common/Models/BaseModel'; import BadDataException from 'Common/Types/Exception/BadDataException'; import ComponentMetadata, { Port } from 'Common/Types/Workflow/Component'; -import DatabaseService from '../../../Services/DatabaseService'; -import ComponentCode, { RunOptions, RunReturnType } from '../ComponentCode'; +import DatabaseService from '../../../../Services/DatabaseService'; +import ComponentCode, { RunOptions, RunReturnType } from '../../ComponentCode'; import BaseModelComponents from 'Common/Types/Workflow/Components/BaseModel'; import Text from 'Common/Types/Text'; import { JSONObject } from 'Common/Types/JSON'; -import Query from '../../Database/Query'; +import Query from '../../../Database/Query'; import { LIMIT_PER_PROJECT } from 'Common/Types/Database/LimitMax'; import PositiveNumber from 'Common/Types/PositiveNumber'; diff --git a/CommonServer/Types/Workflow/Components/DeleteOneBaseModel.ts b/CommonServer/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.ts similarity index 95% rename from CommonServer/Types/Workflow/Components/DeleteOneBaseModel.ts rename to CommonServer/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.ts index 82576afb4c..8a1aa7f412 100644 --- a/CommonServer/Types/Workflow/Components/DeleteOneBaseModel.ts +++ b/CommonServer/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.ts @@ -1,12 +1,12 @@ import BaseModel from 'Common/Models/BaseModel'; import BadDataException from 'Common/Types/Exception/BadDataException'; import ComponentMetadata, { Port } from 'Common/Types/Workflow/Component'; -import DatabaseService from '../../../Services/DatabaseService'; -import ComponentCode, { RunOptions, RunReturnType } from '../ComponentCode'; +import DatabaseService from '../../../../Services/DatabaseService'; +import ComponentCode, { RunOptions, RunReturnType } from '../../ComponentCode'; import BaseModelComponents from 'Common/Types/Workflow/Components/BaseModel'; import Text from 'Common/Types/Text'; import { JSONObject } from 'Common/Types/JSON'; -import Query from '../../Database/Query'; +import Query from '../../../Database/Query'; export default class DeleteOneBaseModel< TBaseModel extends BaseModel diff --git a/CommonServer/Types/Workflow/Components/FindManyBaseModel.ts b/CommonServer/Types/Workflow/Components/BaseModel/FindManyBaseModel.ts similarity index 95% rename from CommonServer/Types/Workflow/Components/FindManyBaseModel.ts rename to CommonServer/Types/Workflow/Components/BaseModel/FindManyBaseModel.ts index 357e985a5f..6836e83f3a 100644 --- a/CommonServer/Types/Workflow/Components/FindManyBaseModel.ts +++ b/CommonServer/Types/Workflow/Components/BaseModel/FindManyBaseModel.ts @@ -1,14 +1,14 @@ import BaseModel from 'Common/Models/BaseModel'; import BadDataException from 'Common/Types/Exception/BadDataException'; import ComponentMetadata, { Port } from 'Common/Types/Workflow/Component'; -import DatabaseService from '../../../Services/DatabaseService'; -import ComponentCode, { RunOptions, RunReturnType } from '../ComponentCode'; +import DatabaseService from '../../../../Services/DatabaseService'; +import ComponentCode, { RunOptions, RunReturnType } from '../../ComponentCode'; import BaseModelComponents from 'Common/Types/Workflow/Components/BaseModel'; import Text from 'Common/Types/Text'; import { JSONObject } from 'Common/Types/JSON'; -import Query from '../../Database/Query'; +import Query from '../../../Database/Query'; import JSONFunctions from 'Common/Types/JSONFunctions'; -import Select from '../../Database/Select'; +import Select from '../../../Database/Select'; import { LIMIT_PER_PROJECT } from 'Common/Types/Database/LimitMax'; import PositiveNumber from 'Common/Types/PositiveNumber'; diff --git a/CommonServer/Types/Workflow/Components/FindOneBaseModel.ts b/CommonServer/Types/Workflow/Components/BaseModel/FindOneBaseModel.ts similarity index 95% rename from CommonServer/Types/Workflow/Components/FindOneBaseModel.ts rename to CommonServer/Types/Workflow/Components/BaseModel/FindOneBaseModel.ts index 3608c8a18f..af4f912a77 100644 --- a/CommonServer/Types/Workflow/Components/FindOneBaseModel.ts +++ b/CommonServer/Types/Workflow/Components/BaseModel/FindOneBaseModel.ts @@ -1,14 +1,14 @@ import BaseModel from 'Common/Models/BaseModel'; import BadDataException from 'Common/Types/Exception/BadDataException'; import ComponentMetadata, { Port } from 'Common/Types/Workflow/Component'; -import DatabaseService from '../../../Services/DatabaseService'; -import ComponentCode, { RunOptions, RunReturnType } from '../ComponentCode'; +import DatabaseService from '../../../../Services/DatabaseService'; +import ComponentCode, { RunOptions, RunReturnType } from '../../ComponentCode'; import BaseModelComponents from 'Common/Types/Workflow/Components/BaseModel'; import Text from 'Common/Types/Text'; import { JSONObject } from 'Common/Types/JSON'; -import Query from '../../Database/Query'; +import Query from '../../../Database/Query'; import JSONFunctions from 'Common/Types/JSONFunctions'; -import Select from '../../Database/Select'; +import Select from '../../../Database/Select'; export default class FindOneBaseModel< TBaseModel extends BaseModel diff --git a/CommonServer/Types/Workflow/Components/OnCreateBaseModel.ts b/CommonServer/Types/Workflow/Components/BaseModel/OnCreateBaseModel.ts similarity index 83% rename from CommonServer/Types/Workflow/Components/OnCreateBaseModel.ts rename to CommonServer/Types/Workflow/Components/BaseModel/OnCreateBaseModel.ts index 6058bc9092..dc85edfecf 100644 --- a/CommonServer/Types/Workflow/Components/OnCreateBaseModel.ts +++ b/CommonServer/Types/Workflow/Components/BaseModel/OnCreateBaseModel.ts @@ -1,5 +1,5 @@ import BaseModel from 'Common/Models/BaseModel'; -import DatabaseService from '../../../Services/DatabaseService'; +import DatabaseService from '../../../../Services/DatabaseService'; import OnTriggerBaseModel from './OnTriggerBaseModel'; export default class OnCreateBaseModel< diff --git a/CommonServer/Types/Workflow/Components/OnDeleteBaseModel.ts b/CommonServer/Types/Workflow/Components/BaseModel/OnDeleteBaseModel.ts similarity index 83% rename from CommonServer/Types/Workflow/Components/OnDeleteBaseModel.ts rename to CommonServer/Types/Workflow/Components/BaseModel/OnDeleteBaseModel.ts index 8a55a15860..b009a895c0 100644 --- a/CommonServer/Types/Workflow/Components/OnDeleteBaseModel.ts +++ b/CommonServer/Types/Workflow/Components/BaseModel/OnDeleteBaseModel.ts @@ -1,5 +1,5 @@ import BaseModel from 'Common/Models/BaseModel'; -import DatabaseService from '../../../Services/DatabaseService'; +import DatabaseService from '../../../../Services/DatabaseService'; import OnTriggerBaseModel from './OnTriggerBaseModel'; export default class OnDeleteBaseModel< diff --git a/CommonServer/Types/Workflow/Components/OnTriggerBaseModel.ts b/CommonServer/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.ts similarity index 90% rename from CommonServer/Types/Workflow/Components/OnTriggerBaseModel.ts rename to CommonServer/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.ts index 385276af5c..585f7f9cf5 100644 --- a/CommonServer/Types/Workflow/Components/OnTriggerBaseModel.ts +++ b/CommonServer/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.ts @@ -2,16 +2,16 @@ import BaseModel from 'Common/Models/BaseModel'; import BadDataException from 'Common/Types/Exception/BadDataException'; import ObjectID from 'Common/Types/ObjectID'; import ComponentMetadata from 'Common/Types/Workflow/Component'; -import DatabaseService from '../../../Services/DatabaseService'; -import { ExpressRequest, ExpressResponse } from '../../../Utils/Express'; -import Response from '../../../Utils/Response'; -import TriggerCode, { ExecuteWorkflowType, InitProps } from '../TriggerCode'; +import DatabaseService from '../../../../Services/DatabaseService'; +import { ExpressRequest, ExpressResponse } from '../../../../Utils/Express'; +import Response from '../../../../Utils/Response'; +import TriggerCode, { ExecuteWorkflowType, InitProps } from '../../TriggerCode'; import BaseModelComponents from 'Common/Types/Workflow/Components/BaseModel'; import Text from 'Common/Types/Text'; -import WorkflowService from '../../../Services/WorkflowService'; +import WorkflowService from '../../../../Services/WorkflowService'; import LIMIT_MAX from 'Common/Types/Database/LimitMax'; import Workflow from 'Model/Models/Workflow'; -import ClusterKeyAuthorization from '../../../Middleware/ClusterKeyAuthorization'; +import ClusterKeyAuthorization from '../../../../Middleware/ClusterKeyAuthorization'; export default class OnTriggerBaseModel< TBaseModel extends BaseModel diff --git a/CommonServer/Types/Workflow/Components/OnUpdateBaseModel.ts b/CommonServer/Types/Workflow/Components/BaseModel/OnUpdateBaseModel.ts similarity index 83% rename from CommonServer/Types/Workflow/Components/OnUpdateBaseModel.ts rename to CommonServer/Types/Workflow/Components/BaseModel/OnUpdateBaseModel.ts index 2726d1f1a2..86450da5d6 100644 --- a/CommonServer/Types/Workflow/Components/OnUpdateBaseModel.ts +++ b/CommonServer/Types/Workflow/Components/BaseModel/OnUpdateBaseModel.ts @@ -1,5 +1,5 @@ import BaseModel from 'Common/Models/BaseModel'; -import DatabaseService from '../../../Services/DatabaseService'; +import DatabaseService from '../../../../Services/DatabaseService'; import OnTriggerBaseModel from './OnTriggerBaseModel'; export default class OnUpdateBaseModel< diff --git a/CommonServer/Types/Workflow/Components/UpdateManyBaseModel.ts b/CommonServer/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.ts similarity index 96% rename from CommonServer/Types/Workflow/Components/UpdateManyBaseModel.ts rename to CommonServer/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.ts index 1d40b4d081..3a74e2328f 100644 --- a/CommonServer/Types/Workflow/Components/UpdateManyBaseModel.ts +++ b/CommonServer/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.ts @@ -1,12 +1,12 @@ import BaseModel from 'Common/Models/BaseModel'; import BadDataException from 'Common/Types/Exception/BadDataException'; import ComponentMetadata, { Port } from 'Common/Types/Workflow/Component'; -import DatabaseService from '../../../Services/DatabaseService'; -import ComponentCode, { RunOptions, RunReturnType } from '../ComponentCode'; +import DatabaseService from '../../../../Services/DatabaseService'; +import ComponentCode, { RunOptions, RunReturnType } from '../../ComponentCode'; import BaseModelComponents from 'Common/Types/Workflow/Components/BaseModel'; import Text from 'Common/Types/Text'; import { JSONObject } from 'Common/Types/JSON'; -import Query from '../../Database/Query'; +import Query from '../../../Database/Query'; import QueryDeepPartialEntity from 'Common/Types/Database/PartialEntity'; import { LIMIT_PER_PROJECT } from 'Common/Types/Database/LimitMax'; import PositiveNumber from 'Common/Types/PositiveNumber'; diff --git a/CommonServer/Types/Workflow/Components/UpdateOneBaseModel.ts b/CommonServer/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.ts similarity index 96% rename from CommonServer/Types/Workflow/Components/UpdateOneBaseModel.ts rename to CommonServer/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.ts index 4310003923..115ad0abc3 100644 --- a/CommonServer/Types/Workflow/Components/UpdateOneBaseModel.ts +++ b/CommonServer/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.ts @@ -1,12 +1,12 @@ import BaseModel from 'Common/Models/BaseModel'; import BadDataException from 'Common/Types/Exception/BadDataException'; import ComponentMetadata, { Port } from 'Common/Types/Workflow/Component'; -import DatabaseService from '../../../Services/DatabaseService'; -import ComponentCode, { RunOptions, RunReturnType } from '../ComponentCode'; +import DatabaseService from '../../../../Services/DatabaseService'; +import ComponentCode, { RunOptions, RunReturnType } from '../../ComponentCode'; import BaseModelComponents from 'Common/Types/Workflow/Components/BaseModel'; import Text from 'Common/Types/Text'; import { JSONObject } from 'Common/Types/JSON'; -import Query from '../../Database/Query'; +import Query from '../../../Database/Query'; import QueryDeepPartialEntity from 'Common/Types/Database/PartialEntity'; export default class UpdateOneBaseModel< diff --git a/CommonServer/Types/Workflow/Components/Index.ts b/CommonServer/Types/Workflow/Components/Index.ts index d7ced7914a..6c513fbd7c 100644 --- a/CommonServer/Types/Workflow/Components/Index.ts +++ b/CommonServer/Types/Workflow/Components/Index.ts @@ -8,17 +8,17 @@ import JavaScirptCode from './JavaScript'; import BaseModelServices from '../../../Services/Index'; import BaseModel from 'Common/Models/BaseModel'; import Text from 'Common/Types/Text'; -import OnCreateBaseModel from './OnCreateBaseModel'; -import CreateOneBaseModel from './CreateOneBaseModel'; -import CreateManyBaseModel from './CreateManyBaseModel'; -import FindOneBaseModel from './FindOneBaseModel'; -import FindManyBaseModel from './FindManyBaseModel'; -import OnUpdateBaseModel from './OnUpdateBaseModel'; -import UpdateOneBaseModel from './UpdateOneBaseModel'; -import UpdateManyBaseModel from './UpdateManyBaseModel'; -import OnDeleteBaseModel from './OnDeleteBaseModel'; -import DeleteOneBaseModel from './DeleteOneBaseModel'; -import DeleteManyBaseModel from './DeleteManyBaseMoidel'; +import OnCreateBaseModel from './BaseModel/OnCreateBaseModel'; +import CreateOneBaseModel from './BaseModel/CreateOneBaseModel'; +import CreateManyBaseModel from './BaseModel/CreateManyBaseModel'; +import FindOneBaseModel from './BaseModel/FindOneBaseModel'; +import FindManyBaseModel from './BaseModel/FindManyBaseModel'; +import OnUpdateBaseModel from './BaseModel/OnUpdateBaseModel'; +import UpdateOneBaseModel from './BaseModel/UpdateOneBaseModel'; +import UpdateManyBaseModel from './BaseModel/UpdateManyBaseModel'; +import OnDeleteBaseModel from './BaseModel/OnDeleteBaseModel'; +import DeleteOneBaseModel from './BaseModel/DeleteOneBaseModel'; +import DeleteManyBaseModel from './BaseModel/DeleteManyBaseMoidel'; import ManualTrigger from './Manual'; const Components: Dictionary = { diff --git a/CommonServer/Types/Workflow/Components/JSON/JsonToText.ts b/CommonServer/Types/Workflow/Components/JSON/JsonToText.ts new file mode 100644 index 0000000000..0e17b4a5c9 --- /dev/null +++ b/CommonServer/Types/Workflow/Components/JSON/JsonToText.ts @@ -0,0 +1,86 @@ +import BadDataException from 'Common/Types/Exception/BadDataException'; +import { JSONObject } from 'Common/Types/JSON'; +import ComponentMetadata, { Port } from 'Common/Types/Workflow/Component'; +import ComponentID from 'Common/Types/Workflow/ComponentID'; +import JSONComponents from 'Common/Types/Workflow/Components/JSON'; +import ComponentCode, { RunOptions, RunReturnType } from '../../ComponentCode'; + +export default class JsonToText extends ComponentCode { + public constructor() { + super(); + + const Component: ComponentMetadata | undefined = JSONComponents.find( + (i: ComponentMetadata) => { + return i.id === ComponentID.JsonToText; + } + ); + + if (!Component) { + throw new BadDataException('Component not found.'); + } + + this.setMetadata(Component); + } + + public override async run( + args: JSONObject, + options: RunOptions + ): Promise { + const successPort: Port | undefined = this.getMetadata().outPorts.find( + (p: Port) => { + return p.id === 'success'; + } + ); + + if (!successPort) { + throw options.onError( + new BadDataException('Success port not found') + ); + } + + const errorPort: Port | undefined = this.getMetadata().outPorts.find( + (p: Port) => { + return p.id === 'error'; + } + ); + + if (!errorPort) { + throw options.onError(new BadDataException('Error port not found')); + } + + if (!args['json']) { + throw options.onError( + new BadDataException('JSON is undefined.') + ); + } + + if (typeof args['json'] === 'string') { + args['json'] = JSON.parse(args['json'] as string); + + } + + if (typeof args['json'] !== 'object') { + throw options.onError( + new BadDataException('JSON is should be of type object.') + ); + } + + try { + + const returnValue: string = JSON.stringify(args['json'] as JSONObject); + return Promise.resolve({ + returnValues: { + text: returnValue + }, + executePort: successPort, + }); + + } catch (err) { + options.log("JSON is not in the correct format."); + return Promise.resolve({ + returnValues: {}, + executePort: errorPort, + }); + } + } +} diff --git a/CommonServer/Types/Workflow/Components/JSON/MergeJson.ts b/CommonServer/Types/Workflow/Components/JSON/MergeJson.ts new file mode 100644 index 0000000000..7293486f93 --- /dev/null +++ b/CommonServer/Types/Workflow/Components/JSON/MergeJson.ts @@ -0,0 +1,96 @@ +import BadDataException from 'Common/Types/Exception/BadDataException'; +import { JSONObject } from 'Common/Types/JSON'; +import ComponentMetadata, { Port } from 'Common/Types/Workflow/Component'; +import ComponentID from 'Common/Types/Workflow/ComponentID'; +import JSONComponents from 'Common/Types/Workflow/Components/JSON'; +import ComponentCode, { RunOptions, RunReturnType } from '../../ComponentCode'; + +export default class JsonToText extends ComponentCode { + public constructor() { + super(); + + const Component: ComponentMetadata | undefined = JSONComponents.find( + (i: ComponentMetadata) => { + return i.id === ComponentID.MergeJson; + } + ); + + if (!Component) { + throw new BadDataException('Component not found.'); + } + + this.setMetadata(Component); + } + + public override async run( + args: JSONObject, + options: RunOptions + ): Promise { + const successPort: Port | undefined = this.getMetadata().outPorts.find( + (p: Port) => { + return p.id === 'success'; + } + ); + + if (!successPort) { + throw options.onError( + new BadDataException('Success port not found') + ); + } + + const errorPort: Port | undefined = this.getMetadata().outPorts.find( + (p: Port) => { + return p.id === 'error'; + } + ); + + if (!errorPort) { + throw options.onError(new BadDataException('Error port not found')); + } + + if (!args['json1']) { + throw options.onError( + new BadDataException('JSON1 is undefined.') + ); + } + + if (typeof args['json1'] === 'string') { + args['json1'] = JSON.parse(args['json1'] as string); + + } + + if (typeof args['json2'] !== 'object') { + throw options.onError( + new BadDataException('JSON2 is should be of type object.') + ); + } + + + if (!args['json2']) { + throw options.onError( + new BadDataException('JSON2 is undefined.') + ); + } + + if (typeof args['json2'] === 'string') { + args['json2'] = JSON.parse(args['json2'] as string); + + } + + if (typeof args['json2'] !== 'object') { + throw options.onError( + new BadDataException('JSON2 is should be of type object.') + ); + } + + return Promise.resolve({ + returnValues: { + json: { + ...args['json1'] as JSONObject, + ...args['json2'] as JSONObject + } + }, + executePort: successPort, + }); + } +} diff --git a/CommonServer/Types/Workflow/Components/JSON/TextToJson.ts b/CommonServer/Types/Workflow/Components/JSON/TextToJson.ts new file mode 100644 index 0000000000..1755486723 --- /dev/null +++ b/CommonServer/Types/Workflow/Components/JSON/TextToJson.ts @@ -0,0 +1,82 @@ +import BadDataException from 'Common/Types/Exception/BadDataException'; +import { JSONObject } from 'Common/Types/JSON'; +import ComponentMetadata, { Port } from 'Common/Types/Workflow/Component'; +import ComponentID from 'Common/Types/Workflow/ComponentID'; +import JSONComponents from 'Common/Types/Workflow/Components/JSON'; +import ComponentCode, { RunOptions, RunReturnType } from '../../ComponentCode'; + +export default class JsonToText extends ComponentCode { + public constructor() { + super(); + + const Component: ComponentMetadata | undefined = JSONComponents.find( + (i: ComponentMetadata) => { + return i.id === ComponentID.TextToJson; + } + ); + + if (!Component) { + throw new BadDataException('Component not found.'); + } + + this.setMetadata(Component); + } + + public override async run( + args: JSONObject, + options: RunOptions + ): Promise { + const successPort: Port | undefined = this.getMetadata().outPorts.find( + (p: Port) => { + return p.id === 'success'; + } + ); + + if (!successPort) { + throw options.onError( + new BadDataException('Success port not found') + ); + } + + const errorPort: Port | undefined = this.getMetadata().outPorts.find( + (p: Port) => { + return p.id === 'error'; + } + ); + + if (!errorPort) { + throw options.onError(new BadDataException('Error port not found')); + } + + if (!args['text']) { + throw options.onError( + new BadDataException('text is undefined.') + ); + } + + + if (typeof args['text'] !== 'string') { + throw options.onError( + new BadDataException('text is should be of type string.') + ); + } + + try { + + const returnValue: JSONObject = JSON.parse(args['text'] as string); + return Promise.resolve({ + returnValues: { + json: returnValue + }, + executePort: successPort, + }); + + } catch (err) { + options.log("text is not in the correct format."); + return Promise.resolve({ + returnValues: {}, + executePort: errorPort, + }); + } + } +} From 370c5bd31cf9136cb372cdcab1c4536cc2f139bd Mon Sep 17 00:00:00 2001 From: Simon Larsen Date: Wed, 1 Mar 2023 14:38:58 +0000 Subject: [PATCH 03/11] add api components --- Common/Types/Workflow/ComponentID.ts | 6 +- Common/Types/Workflow/Components/API.ts | 51 +++++------ .../Types/Workflow/Components/API/Delete.ts | 69 +++++++++++++++ .../Types/Workflow/Components/API/Get.ts | 69 +++++++++++++++ .../Types/Workflow/Components/API/Post.ts | 69 +++++++++++++++ .../Types/Workflow/Components/API/Put.ts | 69 +++++++++++++++ .../Types/Workflow/Components/API/Utils.ts | 87 +++++++++++++++++++ .../Types/Workflow/Components/Index.ts | 6 ++ .../Workflow/Components/JSON/MergeJson.ts | 2 +- .../Workflow/Components/JSON/TextToJson.ts | 2 +- 10 files changed, 402 insertions(+), 28 deletions(-) create mode 100644 CommonServer/Types/Workflow/Components/API/Delete.ts create mode 100644 CommonServer/Types/Workflow/Components/API/Get.ts create mode 100644 CommonServer/Types/Workflow/Components/API/Post.ts create mode 100644 CommonServer/Types/Workflow/Components/API/Put.ts create mode 100644 CommonServer/Types/Workflow/Components/API/Utils.ts diff --git a/Common/Types/Workflow/ComponentID.ts b/Common/Types/Workflow/ComponentID.ts index 31a4d78766..8d003ac0a0 100644 --- a/Common/Types/Workflow/ComponentID.ts +++ b/Common/Types/Workflow/ComponentID.ts @@ -6,7 +6,11 @@ enum ComponentID { Manual = 'manual', JsonToText = 'json-to-text', TextToJson = 'text-to-json', - MergeJson = 'merge-json' + MergeJson = 'merge-json', + ApiGet = 'api-get', + ApiPut = 'api-get', + ApiPost = 'api-get', + ApiDelete = 'api-get', } export default ComponentID; diff --git a/Common/Types/Workflow/Components/API.ts b/Common/Types/Workflow/Components/API.ts index 8eef72d456..604e60aa1f 100644 --- a/Common/Types/Workflow/Components/API.ts +++ b/Common/Types/Workflow/Components/API.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: 'api-get', + id: ComponentID.ApiGet, title: 'API Get (JSON)', category: 'API', description: 'Send Get API Request and get JSON Response', @@ -26,8 +27,8 @@ const components: Array = [ name: 'Request Body', description: 'Request Body in JSON', type: ComponentInputType.JSON, - required: true, - placeholder: '{"key1": "value1", "key2": "value2", ....}', + required: false, + placeholder: 'Example: {"key1": "value1", "key2": "value2", ....}', }, { id: 'query-string', @@ -36,7 +37,7 @@ const components: Array = [ type: ComponentInputType.StringDictionary, required: false, isAdvanced: true, - placeholder: '{"query1": "value1", "query2": "value2", ....}', + placeholder: 'Example: {"query1": "value1", "query2": "value2", ....}', }, { id: 'request-headers', @@ -45,7 +46,7 @@ const components: Array = [ type: ComponentInputType.StringDictionary, required: false, isAdvanced: true, - placeholder: '{"header1": "value1", "header2": "value2", ....}', + placeholder: 'Example: {"header1": "value1", "header2": "value2", ....}', }, ], returnValues: [ @@ -57,7 +58,7 @@ const components: Array = [ required: false, }, { - id: 'status', + id: 'response-status', name: 'Response Status', description: 'Response Status (200, for example)', type: ComponentInputType.Number, @@ -101,7 +102,7 @@ const components: Array = [ ], }, { - id: 'api-post', + id: ComponentID.ApiPost, title: 'API Post (JSON)', category: 'API', description: 'Send a POST Request and get JSON Response', @@ -121,8 +122,8 @@ const components: Array = [ name: 'Request Body', description: 'Request Body in JSON', type: ComponentInputType.JSON, - required: true, - placeholder: '{"key1": "value1", "key2": "value2", ....}', + required: false, + placeholder: 'Example: {"key1": "value1", "key2": "value2", ....}', }, { id: 'query-string', @@ -131,7 +132,7 @@ const components: Array = [ type: ComponentInputType.StringDictionary, required: false, isAdvanced: true, - placeholder: '{"query1": "value1", "query2": "value2", ....}', + placeholder: 'Example: {"query1": "value1", "query2": "value2", ....}', }, { id: 'request-headers', @@ -140,7 +141,7 @@ const components: Array = [ type: ComponentInputType.StringDictionary, required: false, isAdvanced: true, - placeholder: '{"header1": "value1", "header2": "value2", ....}', + placeholder: 'Example: {"header1": "value1", "header2": "value2", ....}', }, ], returnValues: [ @@ -152,7 +153,7 @@ const components: Array = [ required: false, }, { - id: 'status', + id: 'response-status', name: 'Response Status', description: 'Response Status (200, for example)', type: ComponentInputType.Number, @@ -196,8 +197,8 @@ const components: Array = [ ], }, { - id: 'api-patch', - title: 'API Patch (JSON)', + id: ComponentID.ApiPut, + title: 'API Put (JSON)', category: 'API', description: 'Send a PATCH Request and get JSON Response', iconProp: IconProp.Globe, @@ -216,8 +217,8 @@ const components: Array = [ name: 'Request Body', description: 'Request Body in JSON', type: ComponentInputType.JSON, - required: true, - placeholder: '{"key1": "value1", "key2": "value2", ....}', + required: false, + placeholder: 'Example: {"key1": "value1", "key2": "value2", ....}', }, { id: 'query-string', @@ -226,7 +227,7 @@ const components: Array = [ type: ComponentInputType.StringDictionary, required: false, isAdvanced: true, - placeholder: '{"query1": "value1", "query2": "value2", ....}', + placeholder: 'Example: {"query1": "value1", "query2": "value2", ....}', }, { id: 'request-headers', @@ -235,7 +236,7 @@ const components: Array = [ type: ComponentInputType.StringDictionary, required: false, isAdvanced: true, - placeholder: '{"header1": "value1", "header2": "value2", ....}', + placeholder: 'Example: {"header1": "value1", "header2": "value2", ....}', }, ], returnValues: [ @@ -247,7 +248,7 @@ const components: Array = [ required: false, }, { - id: 'status', + id: 'response-status', name: 'Response Status', description: 'Response Status (200, for example)', type: ComponentInputType.Number, @@ -291,7 +292,7 @@ const components: Array = [ ], }, { - id: 'api-delete', + id: ComponentID.ApiDelete, title: 'API Delete (JSON)', category: 'API', description: 'Send a PATCH Request and get JSON Response', @@ -311,8 +312,8 @@ const components: Array = [ name: 'Request Body', description: 'Request Body in JSON', type: ComponentInputType.JSON, - required: true, - placeholder: '{"key1": "value1", "key2": "value2", ....}', + required: false, + placeholder: 'Example: {"key1": "value1", "key2": "value2", ....}', }, { id: 'query-string', @@ -321,7 +322,7 @@ const components: Array = [ type: ComponentInputType.StringDictionary, required: false, isAdvanced: true, - placeholder: '{"query1": "value1", "query2": "value2", ....}', + placeholder: 'Example: {"query1": "value1", "query2": "value2", ....}', }, { id: 'request-headers', @@ -330,7 +331,7 @@ const components: Array = [ type: ComponentInputType.StringDictionary, required: false, isAdvanced: true, - placeholder: '{"header1": "value1", "header2": "value2", ....}', + placeholder: 'Example: {"header1": "value1", "header2": "value2", ....}', }, ], returnValues: [ @@ -342,7 +343,7 @@ const components: Array = [ required: false, }, { - id: 'status', + id: 'response-status', name: 'Response Status', description: 'Response Status (200, for example)', type: ComponentInputType.Number, diff --git a/CommonServer/Types/Workflow/Components/API/Delete.ts b/CommonServer/Types/Workflow/Components/API/Delete.ts new file mode 100644 index 0000000000..0e7c45aadb --- /dev/null +++ b/CommonServer/Types/Workflow/Components/API/Delete.ts @@ -0,0 +1,69 @@ +import BadDataException from 'Common/Types/Exception/BadDataException'; +import { JSONObject } from 'Common/Types/JSON'; +import ComponentMetadata, { Port } from 'Common/Types/Workflow/Component'; +import ComponentID from 'Common/Types/Workflow/ComponentID'; +import JSONComponents from 'Common/Types/Workflow/Components/API'; +import API from 'Common/Utils/API'; +import ComponentCode, { RunOptions, RunReturnType } from '../../ComponentCode'; +import { ApiComponentUtils } from './Utils'; +import URL from 'Common/Types/API/URL'; +import Dictionary from 'Common/Types/Dictionary'; +import HTTPResponse from 'Common/Types/API/HTTPResponse'; +import HTTPErrorResponse from 'Common/Types/API/HTTPErrorResponse'; +import APIException from 'Common/Types/Exception/ApiException'; + +export default class ApiDelete extends ComponentCode { + public constructor() { + super(); + + const Component: ComponentMetadata | undefined = JSONComponents.find( + (i: ComponentMetadata) => { + return i.id === ComponentID.ApiDelete; + } + ); + + if (!Component) { + throw new BadDataException('Component not found.'); + } + + this.setMetadata(Component); + } + + public override async run( + args: JSONObject, + options: RunOptions + ): Promise { + + const result: { args: JSONObject, successPort: Port, errorPort: Port } = ApiComponentUtils.sanitizeArgs(this.getMetadata(), args, options); + + let apiResult: HTTPResponse | HTTPErrorResponse | null = null; + + try { + + apiResult = await API.delete(args['url'] as URL, args['request-body'] as JSONObject, args['request-headers'] as Dictionary); + + return Promise.resolve({ + returnValues: ApiComponentUtils.getReturnValues(apiResult), + executePort: result.successPort, + }); + + } catch (err) { + + if (err instanceof HTTPErrorResponse) { + return Promise.resolve({ + returnValues: ApiComponentUtils.getReturnValues(err), + executePort: result.successPort, + }); + } + + if (apiResult) { + return Promise.resolve({ + returnValues: ApiComponentUtils.getReturnValues(apiResult), + executePort: result.successPort, + }); + } + + throw options.onError(new APIException("Something wrong happened.")); + } + } +} diff --git a/CommonServer/Types/Workflow/Components/API/Get.ts b/CommonServer/Types/Workflow/Components/API/Get.ts new file mode 100644 index 0000000000..d0fdbef910 --- /dev/null +++ b/CommonServer/Types/Workflow/Components/API/Get.ts @@ -0,0 +1,69 @@ +import BadDataException from 'Common/Types/Exception/BadDataException'; +import { JSONObject } from 'Common/Types/JSON'; +import ComponentMetadata, { Port } from 'Common/Types/Workflow/Component'; +import ComponentID from 'Common/Types/Workflow/ComponentID'; +import JSONComponents from 'Common/Types/Workflow/Components/API'; +import API from 'Common/Utils/API'; +import ComponentCode, { RunOptions, RunReturnType } from '../../ComponentCode'; +import { ApiComponentUtils } from './Utils'; +import URL from 'Common/Types/API/URL'; +import Dictionary from 'Common/Types/Dictionary'; +import HTTPResponse from 'Common/Types/API/HTTPResponse'; +import HTTPErrorResponse from 'Common/Types/API/HTTPErrorResponse'; +import APIException from 'Common/Types/Exception/ApiException'; + +export default class ApiGet extends ComponentCode { + public constructor() { + super(); + + const Component: ComponentMetadata | undefined = JSONComponents.find( + (i: ComponentMetadata) => { + return i.id === ComponentID.ApiGet; + } + ); + + if (!Component) { + throw new BadDataException('Component not found.'); + } + + this.setMetadata(Component); + } + + public override async run( + args: JSONObject, + options: RunOptions + ): Promise { + + const result: { args: JSONObject, successPort: Port, errorPort: Port } = ApiComponentUtils.sanitizeArgs(this.getMetadata(), args, options); + + let apiResult: HTTPResponse | HTTPErrorResponse | null = null; + + try { + + apiResult = await API.get(args['url'] as URL, args['request-body'] as JSONObject, args['request-headers'] as Dictionary); + + return Promise.resolve({ + returnValues: ApiComponentUtils.getReturnValues(apiResult), + executePort: result.successPort, + }); + + } catch (err) { + + if (err instanceof HTTPErrorResponse) { + return Promise.resolve({ + returnValues: ApiComponentUtils.getReturnValues(err), + executePort: result.successPort, + }); + } + + if (apiResult) { + return Promise.resolve({ + returnValues: ApiComponentUtils.getReturnValues(apiResult), + executePort: result.successPort, + }); + } + + throw options.onError(new APIException("Something wrong happened.")); + } + } +} diff --git a/CommonServer/Types/Workflow/Components/API/Post.ts b/CommonServer/Types/Workflow/Components/API/Post.ts new file mode 100644 index 0000000000..53edb4bd5a --- /dev/null +++ b/CommonServer/Types/Workflow/Components/API/Post.ts @@ -0,0 +1,69 @@ +import BadDataException from 'Common/Types/Exception/BadDataException'; +import { JSONObject } from 'Common/Types/JSON'; +import ComponentMetadata, { Port } from 'Common/Types/Workflow/Component'; +import ComponentID from 'Common/Types/Workflow/ComponentID'; +import JSONComponents from 'Common/Types/Workflow/Components/API'; +import API from 'Common/Utils/API'; +import ComponentCode, { RunOptions, RunReturnType } from '../../ComponentCode'; +import { ApiComponentUtils } from './Utils'; +import URL from 'Common/Types/API/URL'; +import Dictionary from 'Common/Types/Dictionary'; +import HTTPResponse from 'Common/Types/API/HTTPResponse'; +import HTTPErrorResponse from 'Common/Types/API/HTTPErrorResponse'; +import APIException from 'Common/Types/Exception/ApiException'; + +export default class ApiPost extends ComponentCode { + public constructor() { + super(); + + const Component: ComponentMetadata | undefined = JSONComponents.find( + (i: ComponentMetadata) => { + return i.id === ComponentID.ApiPost; + } + ); + + if (!Component) { + throw new BadDataException('Component not found.'); + } + + this.setMetadata(Component); + } + + public override async run( + args: JSONObject, + options: RunOptions + ): Promise { + + const result: { args: JSONObject, successPort: Port, errorPort: Port } = ApiComponentUtils.sanitizeArgs(this.getMetadata(), args, options); + + let apiResult: HTTPResponse | HTTPErrorResponse | null = null; + + try { + + apiResult = await API.post(args['url'] as URL, args['request-body'] as JSONObject, args['request-headers'] as Dictionary); + + return Promise.resolve({ + returnValues: ApiComponentUtils.getReturnValues(apiResult), + executePort: result.successPort, + }); + + } catch (err) { + + if (err instanceof HTTPErrorResponse) { + return Promise.resolve({ + returnValues: ApiComponentUtils.getReturnValues(err), + executePort: result.successPort, + }); + } + + if (apiResult) { + return Promise.resolve({ + returnValues: ApiComponentUtils.getReturnValues(apiResult), + executePort: result.successPort, + }); + } + + throw options.onError(new APIException("Something wrong happened.")); + } + } +} diff --git a/CommonServer/Types/Workflow/Components/API/Put.ts b/CommonServer/Types/Workflow/Components/API/Put.ts new file mode 100644 index 0000000000..3cc9f4a9dc --- /dev/null +++ b/CommonServer/Types/Workflow/Components/API/Put.ts @@ -0,0 +1,69 @@ +import BadDataException from 'Common/Types/Exception/BadDataException'; +import { JSONObject } from 'Common/Types/JSON'; +import ComponentMetadata, { Port } from 'Common/Types/Workflow/Component'; +import ComponentID from 'Common/Types/Workflow/ComponentID'; +import JSONComponents from 'Common/Types/Workflow/Components/API'; +import API from 'Common/Utils/API'; +import ComponentCode, { RunOptions, RunReturnType } from '../../ComponentCode'; +import { ApiComponentUtils } from './Utils'; +import URL from 'Common/Types/API/URL'; +import Dictionary from 'Common/Types/Dictionary'; +import HTTPResponse from 'Common/Types/API/HTTPResponse'; +import HTTPErrorResponse from 'Common/Types/API/HTTPErrorResponse'; +import APIException from 'Common/Types/Exception/ApiException'; + +export default class ApiPut extends ComponentCode { + public constructor() { + super(); + + const Component: ComponentMetadata | undefined = JSONComponents.find( + (i: ComponentMetadata) => { + return i.id === ComponentID.ApiPut; + } + ); + + if (!Component) { + throw new BadDataException('Component not found.'); + } + + this.setMetadata(Component); + } + + public override async run( + args: JSONObject, + options: RunOptions + ): Promise { + + const result: { args: JSONObject, successPort: Port, errorPort: Port } = ApiComponentUtils.sanitizeArgs(this.getMetadata(), args, options); + + let apiResult: HTTPResponse | HTTPErrorResponse | null = null; + + try { + + apiResult = await API.put(args['url'] as URL, args['request-body'] as JSONObject, args['request-headers'] as Dictionary); + + return Promise.resolve({ + returnValues: ApiComponentUtils.getReturnValues(apiResult), + executePort: result.successPort, + }); + + } catch (err) { + + if (err instanceof HTTPErrorResponse) { + return Promise.resolve({ + returnValues: ApiComponentUtils.getReturnValues(err), + executePort: result.successPort, + }); + } + + if (apiResult) { + return Promise.resolve({ + returnValues: ApiComponentUtils.getReturnValues(apiResult), + executePort: result.successPort, + }); + } + + throw options.onError(new APIException("Something wrong happened.")); + } + } +} diff --git a/CommonServer/Types/Workflow/Components/API/Utils.ts b/CommonServer/Types/Workflow/Components/API/Utils.ts new file mode 100644 index 0000000000..cf73b77b82 --- /dev/null +++ b/CommonServer/Types/Workflow/Components/API/Utils.ts @@ -0,0 +1,87 @@ +import BadDataException from "Common/Types/Exception/BadDataException"; +import { JSONObject } from "Common/Types/JSON"; +import ComponentMetadata, { Port } from "Common/Types/Workflow/Component"; +import { RunOptions } from "../../ComponentCode"; +import URL from "Common/Types/API/URL"; +import HTTPResponse from "Common/Types/API/HTTPResponse"; +import HTTPErrorResponse from "Common/Types/API/HTTPErrorResponse"; + +export class ApiComponentUtils { + + + public static getReturnValues(response: HTTPResponse | HTTPErrorResponse): JSONObject { + + + if(response instanceof HTTPErrorResponse){ + return { + "response-status": response.statusCode, + "response-body": response.jsonData, + "response-headers": response.headers, + "error": response.message || "Server Error." + } + } + + return { + "response-status": response.statusCode, + "response-body": response.jsonData, + "response-headers": response.headers, + "error": null + } + } + + public static sanitizeArgs(metadata: ComponentMetadata, args: JSONObject, + options: RunOptions): {args: JSONObject, successPort: Port, errorPort: Port} { + const successPort: Port | undefined = metadata.outPorts.find( + (p: Port) => { + return p.id === 'success'; + } + ); + + if (!successPort) { + throw options.onError( + new BadDataException('Success port not found') + ); + } + + const errorPort: Port | undefined = metadata.outPorts.find( + (p: Port) => { + return p.id === 'error'; + } + ); + + if (!errorPort) { + throw options.onError(new BadDataException('Error port not found')); + } + + + if (args['request-body'] && typeof args['request-body'] === 'string') { + args['request-body'] = JSON.parse(args['request-body'] as string); + + } + + if (args['query-string'] && typeof args['query-string'] === 'string') { + args['query-string'] = JSON.parse(args['query-string'] as string); + + } + + if (args['request-headers'] && typeof args['request-headers'] === 'string') { + args['request-headers'] = JSON.parse(args['request-headers'] as string); + } + + if(!args['url']){ + throw options.onError( + new BadDataException('URL not found') + ); + } + + if(args['url'] && typeof args["url"] !== "string"){ + throw options.onError( + new BadDataException('URL is not type of string') + ); + } + + args['url'] = URL.fromString(args["url"] as string); + + return {args, successPort, errorPort}; + } +} \ No newline at end of file diff --git a/CommonServer/Types/Workflow/Components/Index.ts b/CommonServer/Types/Workflow/Components/Index.ts index 6c513fbd7c..cba9bfb143 100644 --- a/CommonServer/Types/Workflow/Components/Index.ts +++ b/CommonServer/Types/Workflow/Components/Index.ts @@ -20,6 +20,9 @@ import OnDeleteBaseModel from './BaseModel/OnDeleteBaseModel'; import DeleteOneBaseModel from './BaseModel/DeleteOneBaseModel'; import DeleteManyBaseModel from './BaseModel/DeleteManyBaseMoidel'; import ManualTrigger from './Manual'; +import JsonToText from './JSON/JsonToText'; +import MergeJSON from './JSON/MergeJson'; +import TextToJSON from './JSON/TextToJson'; const Components: Dictionary = { [ComponentID.Webhook]: new WebhookTrigger(), @@ -27,6 +30,9 @@ const Components: Dictionary = { [ComponentID.Schedule]: new Schedule(), [ComponentID.JavaScriptCode]: new JavaScirptCode(), [ComponentID.Manual]: new ManualTrigger(), + [ComponentID.JsonToText]: new JsonToText(), + [ComponentID.MergeJson]: new MergeJSON(), + [ComponentID.TextToJson]: new TextToJSON(), }; for (const baseModelService of BaseModelServices) { diff --git a/CommonServer/Types/Workflow/Components/JSON/MergeJson.ts b/CommonServer/Types/Workflow/Components/JSON/MergeJson.ts index 7293486f93..3127713dbb 100644 --- a/CommonServer/Types/Workflow/Components/JSON/MergeJson.ts +++ b/CommonServer/Types/Workflow/Components/JSON/MergeJson.ts @@ -5,7 +5,7 @@ import ComponentID from 'Common/Types/Workflow/ComponentID'; import JSONComponents from 'Common/Types/Workflow/Components/JSON'; import ComponentCode, { RunOptions, RunReturnType } from '../../ComponentCode'; -export default class JsonToText extends ComponentCode { +export default class MergeJSON extends ComponentCode { public constructor() { super(); diff --git a/CommonServer/Types/Workflow/Components/JSON/TextToJson.ts b/CommonServer/Types/Workflow/Components/JSON/TextToJson.ts index 1755486723..a54d5dabc5 100644 --- a/CommonServer/Types/Workflow/Components/JSON/TextToJson.ts +++ b/CommonServer/Types/Workflow/Components/JSON/TextToJson.ts @@ -5,7 +5,7 @@ import ComponentID from 'Common/Types/Workflow/ComponentID'; import JSONComponents from 'Common/Types/Workflow/Components/JSON'; import ComponentCode, { RunOptions, RunReturnType } from '../../ComponentCode'; -export default class JsonToText extends ComponentCode { +export default class TextToJSON extends ComponentCode { public constructor() { super(); From de20551d390515561c5809d282d152fc6003e244 Mon Sep 17 00:00:00 2001 From: Simon Larsen Date: Wed, 1 Mar 2023 14:40:10 +0000 Subject: [PATCH 04/11] add api comp to index --- CommonServer/Types/Workflow/Components/Index.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CommonServer/Types/Workflow/Components/Index.ts b/CommonServer/Types/Workflow/Components/Index.ts index cba9bfb143..f0b195c252 100644 --- a/CommonServer/Types/Workflow/Components/Index.ts +++ b/CommonServer/Types/Workflow/Components/Index.ts @@ -23,6 +23,10 @@ import ManualTrigger from './Manual'; import JsonToText from './JSON/JsonToText'; import MergeJSON from './JSON/MergeJson'; import TextToJSON from './JSON/TextToJson'; +import ApiGet from './API/Get'; +import ApiDelete from './API/Delete'; +import ApiPost from './API/Post'; +import ApiPut from './API/Put'; const Components: Dictionary = { [ComponentID.Webhook]: new WebhookTrigger(), @@ -33,6 +37,11 @@ const Components: Dictionary = { [ComponentID.JsonToText]: new JsonToText(), [ComponentID.MergeJson]: new MergeJSON(), [ComponentID.TextToJson]: new TextToJSON(), + [ComponentID.ApiGet]: new ApiGet(), + [ComponentID.ApiPost]: new ApiDelete(), + [ComponentID.ApiDelete]: new ApiPost(), + [ComponentID.ApiPut]: new ApiPut(), + }; for (const baseModelService of BaseModelServices) { From ab109d8f03a3cc45405a7311cb0d126138a7bc5e Mon Sep 17 00:00:00 2001 From: Simon Larsen Date: Wed, 1 Mar 2023 19:44:20 +0000 Subject: [PATCH 05/11] add email sending --- Common/Types/Workflow/Component.ts | 1 + Common/Types/Workflow/ComponentID.ts | 1 + Common/Types/Workflow/Components/Email.ts | 39 ++-- .../Types/Workflow/Components/API/Delete.ts | 4 +- .../Types/Workflow/Components/API/Get.ts | 4 +- .../Types/Workflow/Components/API/Post.ts | 4 +- .../Types/Workflow/Components/API/Put.ts | 4 +- .../Types/Workflow/Components/Email.ts | 166 ++++++++++++++++++ CommonServer/package-lock.json | 17 ++ CommonServer/package.json | 1 + CommonUI/src/Components/Workflow/Utils.ts | 7 + 11 files changed, 228 insertions(+), 20 deletions(-) create mode 100644 CommonServer/Types/Workflow/Components/Email.ts diff --git a/Common/Types/Workflow/Component.ts b/Common/Types/Workflow/Component.ts index 5619faa4f4..07dd3e8908 100644 --- a/Common/Types/Workflow/Component.ts +++ b/Common/Types/Workflow/Component.ts @@ -22,6 +22,7 @@ export enum ComponentInputType { BaseModelArray = 'Database Records', JSONArray = 'List of JSON', LongText = 'Long Text', + HTML = 'HTML' } export enum ComponentType { diff --git a/Common/Types/Workflow/ComponentID.ts b/Common/Types/Workflow/ComponentID.ts index 8d003ac0a0..455d7adabc 100644 --- a/Common/Types/Workflow/ComponentID.ts +++ b/Common/Types/Workflow/ComponentID.ts @@ -11,6 +11,7 @@ enum ComponentID { ApiPut = 'api-get', ApiPost = 'api-get', ApiDelete = 'api-get', + SendEmail = 'send-email' } export default ComponentID; diff --git a/Common/Types/Workflow/Components/Email.ts b/Common/Types/Workflow/Components/Email.ts index 14f5b4bc31..f95539d3b8 100644 --- a/Common/Types/Workflow/Components/Email.ts +++ b/Common/Types/Workflow/Components/Email.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: 'send-email', + id: ComponentID.SendEmail, title: 'Send Email', category: 'Email', description: 'Send email from your workflows', @@ -15,10 +16,19 @@ const components: Array = [ arguments: [ { type: ComponentInputType.Text, - name: 'Email', - description: 'Email to send to', + name: 'From Email', + description: 'Email to send from', + placeholder: "Name ", required: true, - id: 'email', + id: 'from', + }, + { + type: ComponentInputType.Text, + name: 'To Email', + description: 'Email to send to', + placeholder: "email@company.com; email2@company.com; ...", + required: true, + id: 'to', }, { type: ComponentInputType.Text, @@ -28,7 +38,7 @@ const components: Array = [ id: 'subject', }, { - type: ComponentInputType.LongText, + type: ComponentInputType.HTML, name: 'Email Body', description: 'Email to send to', required: false, @@ -39,28 +49,28 @@ const components: Array = [ name: 'SMTP HOST', description: 'SMTP Host to send emails from', required: true, - id: 'smtp_host', + id: 'smtp-host', }, { type: ComponentInputType.Text, name: 'SMTP Username', description: 'SMTP Username to send emails from', required: true, - id: 'smtp_username', + id: 'smtp-username', }, { type: ComponentInputType.Password, name: 'SMTP Password', description: 'SMTP Password to send emails from', required: true, - id: 'smtp_password', + id: 'smtp-password', }, { type: ComponentInputType.Number, name: 'SMTP Port', description: 'SMTP Port to send emails from', required: true, - id: 'smtp_port', + id: 'smtp-port', }, { type: ComponentInputType.Boolean, @@ -82,10 +92,15 @@ const components: Array = [ ], outPorts: [ { - title: 'Email Sent', + title: 'Success', description: - 'Connect to this port if you want other componets to execute after the email is sent.', - id: 'out', + 'This is executed when the message is successfully posted', + id: 'success', + }, + { + title: 'Error', + description: 'This is executed when there is an error', + id: 'error', }, ], }, diff --git a/CommonServer/Types/Workflow/Components/API/Delete.ts b/CommonServer/Types/Workflow/Components/API/Delete.ts index 0e7c45aadb..7cdd703e3c 100644 --- a/CommonServer/Types/Workflow/Components/API/Delete.ts +++ b/CommonServer/Types/Workflow/Components/API/Delete.ts @@ -2,7 +2,7 @@ import BadDataException from 'Common/Types/Exception/BadDataException'; import { JSONObject } from 'Common/Types/JSON'; import ComponentMetadata, { Port } from 'Common/Types/Workflow/Component'; import ComponentID from 'Common/Types/Workflow/ComponentID'; -import JSONComponents from 'Common/Types/Workflow/Components/API'; +import APIComponents from 'Common/Types/Workflow/Components/API'; import API from 'Common/Utils/API'; import ComponentCode, { RunOptions, RunReturnType } from '../../ComponentCode'; import { ApiComponentUtils } from './Utils'; @@ -16,7 +16,7 @@ export default class ApiDelete extends ComponentCode { public constructor() { super(); - const Component: ComponentMetadata | undefined = JSONComponents.find( + const Component: ComponentMetadata | undefined = APIComponents.find( (i: ComponentMetadata) => { return i.id === ComponentID.ApiDelete; } diff --git a/CommonServer/Types/Workflow/Components/API/Get.ts b/CommonServer/Types/Workflow/Components/API/Get.ts index d0fdbef910..de82fab84c 100644 --- a/CommonServer/Types/Workflow/Components/API/Get.ts +++ b/CommonServer/Types/Workflow/Components/API/Get.ts @@ -2,7 +2,7 @@ import BadDataException from 'Common/Types/Exception/BadDataException'; import { JSONObject } from 'Common/Types/JSON'; import ComponentMetadata, { Port } from 'Common/Types/Workflow/Component'; import ComponentID from 'Common/Types/Workflow/ComponentID'; -import JSONComponents from 'Common/Types/Workflow/Components/API'; +import APIComponents from 'Common/Types/Workflow/Components/API'; import API from 'Common/Utils/API'; import ComponentCode, { RunOptions, RunReturnType } from '../../ComponentCode'; import { ApiComponentUtils } from './Utils'; @@ -16,7 +16,7 @@ export default class ApiGet extends ComponentCode { public constructor() { super(); - const Component: ComponentMetadata | undefined = JSONComponents.find( + const Component: ComponentMetadata | undefined = APIComponents.find( (i: ComponentMetadata) => { return i.id === ComponentID.ApiGet; } diff --git a/CommonServer/Types/Workflow/Components/API/Post.ts b/CommonServer/Types/Workflow/Components/API/Post.ts index 53edb4bd5a..d296f6ea5a 100644 --- a/CommonServer/Types/Workflow/Components/API/Post.ts +++ b/CommonServer/Types/Workflow/Components/API/Post.ts @@ -2,7 +2,7 @@ import BadDataException from 'Common/Types/Exception/BadDataException'; import { JSONObject } from 'Common/Types/JSON'; import ComponentMetadata, { Port } from 'Common/Types/Workflow/Component'; import ComponentID from 'Common/Types/Workflow/ComponentID'; -import JSONComponents from 'Common/Types/Workflow/Components/API'; +import APIComponents from 'Common/Types/Workflow/Components/API'; import API from 'Common/Utils/API'; import ComponentCode, { RunOptions, RunReturnType } from '../../ComponentCode'; import { ApiComponentUtils } from './Utils'; @@ -16,7 +16,7 @@ export default class ApiPost extends ComponentCode { public constructor() { super(); - const Component: ComponentMetadata | undefined = JSONComponents.find( + const Component: ComponentMetadata | undefined = APIComponents.find( (i: ComponentMetadata) => { return i.id === ComponentID.ApiPost; } diff --git a/CommonServer/Types/Workflow/Components/API/Put.ts b/CommonServer/Types/Workflow/Components/API/Put.ts index 3cc9f4a9dc..ce4fc72c81 100644 --- a/CommonServer/Types/Workflow/Components/API/Put.ts +++ b/CommonServer/Types/Workflow/Components/API/Put.ts @@ -2,7 +2,7 @@ import BadDataException from 'Common/Types/Exception/BadDataException'; import { JSONObject } from 'Common/Types/JSON'; import ComponentMetadata, { Port } from 'Common/Types/Workflow/Component'; import ComponentID from 'Common/Types/Workflow/ComponentID'; -import JSONComponents from 'Common/Types/Workflow/Components/API'; +import APIComponents from 'Common/Types/Workflow/Components/API'; import API from 'Common/Utils/API'; import ComponentCode, { RunOptions, RunReturnType } from '../../ComponentCode'; import { ApiComponentUtils } from './Utils'; @@ -16,7 +16,7 @@ export default class ApiPut extends ComponentCode { public constructor() { super(); - const Component: ComponentMetadata | undefined = JSONComponents.find( + const Component: ComponentMetadata | undefined = APIComponents.find( (i: ComponentMetadata) => { return i.id === ComponentID.ApiPut; } diff --git a/CommonServer/Types/Workflow/Components/Email.ts b/CommonServer/Types/Workflow/Components/Email.ts new file mode 100644 index 0000000000..dd91a496e3 --- /dev/null +++ b/CommonServer/Types/Workflow/Components/Email.ts @@ -0,0 +1,166 @@ +import BadDataException from 'Common/Types/Exception/BadDataException'; +import { JSONObject } from 'Common/Types/JSON'; +import ComponentMetadata, { Port } from 'Common/Types/Workflow/Component'; +import ComponentID from 'Common/Types/Workflow/ComponentID'; +import Components from 'Common/Types/Workflow/Components/Email'; +import ComponentCode, { RunOptions, RunReturnType } from '../ComponentCode'; +import nodemailer, { Transporter } from 'nodemailer'; + +export default class Email extends ComponentCode { + public constructor() { + super(); + + const Component: ComponentMetadata | undefined = Components.find( + (i: ComponentMetadata) => { + return i.id === ComponentID.SendEmail; + } + ); + + if (!Component) { + throw new BadDataException('Component not found.'); + } + + this.setMetadata(Component); + } + + public override async run( + args: JSONObject, + options: RunOptions + ): Promise { + + + const successPort: Port | undefined = this.getMetadata().outPorts.find( + (p: Port) => { + return p.id === 'success'; + } + ); + + if (!successPort) { + throw options.onError( + new BadDataException('Success port not found') + ); + } + + const errorPort: Port | undefined = this.getMetadata().outPorts.find( + (p: Port) => { + return p.id === 'error'; + } + ); + + if (!errorPort) { + throw options.onError(new BadDataException('Error port not found')); + } + + if (!args['to']) { + throw options.onError( + new BadDataException('to not found') + ); + } + + if (args['to'] && typeof args["to"] !== "string") { + throw options.onError( + new BadDataException('to is not type of string') + ); + } + + if (!args['from']) { + throw options.onError( + new BadDataException('from not found') + ); + } + + if (args['from'] && typeof args["from"] !== "string") { + throw options.onError( + new BadDataException('from is not type of string') + ); + } + + + if (!args['smtp-username']) { + throw options.onError( + new BadDataException('email not found') + ); + } + + if (args['smtp-username'] && typeof args["smtp-username"] !== "string") { + throw options.onError( + new BadDataException('smtp-username is not type of string') + ); + } + + + if (!args['smtp-password']) { + throw options.onError( + new BadDataException('email not found') + ); + } + + if (args['smtp-password'] && typeof args["smtp-password"] !== "string") { + throw options.onError( + new BadDataException('smtp-username is not type of string') + ); + } + + if (!args['smtp-host']) { + throw options.onError( + new BadDataException('email not found') + ); + } + + if (args['smtp-host'] && typeof args["smtp-host"] !== "string") { + throw options.onError( + new BadDataException('smtp-host is not type of string') + ); + } + + if (!args['smtp-port']) { + throw options.onError( + new BadDataException('email not found') + ); + } + + if (args['smtp-port'] && typeof args["smtp-port"] === "string") { + args['smtp-port'] = parseInt(args['smtp-port']); + } + + if (args['smtp-port'] && typeof args["smtp-port"] !== "number") { + throw options.onError( + new BadDataException('smtp-host is not type of number') + ); + } + + try { + + const mailer: Transporter = nodemailer.createTransport({ + host: args['smtp-host']?.toString(), + port: args['smtp-port'] as number, + secure: !!args['secure'], + auth: { + user: args['smtp-username'] as string, + pass: args['smtp-password'] as string, + } + }); + + await mailer.sendMail({ + from: args['from'].toString(), + to: args['to'].toString(), + subject: args['subject']?.toString() || '', + html: args['body']?.toString() || '', + }); + + options.log("Email sent."); + + return Promise.resolve({ + returnValues: {}, + executePort: successPort, + }); + + } catch (err) { + options.log(err); + return Promise.resolve({ + returnValues: {}, + executePort: successPort, + }); + } + } +} diff --git a/CommonServer/package-lock.json b/CommonServer/package-lock.json index 7df174cfb3..cd3e373929 100644 --- a/CommonServer/package-lock.json +++ b/CommonServer/package-lock.json @@ -16,6 +16,7 @@ "@types/ejs": "^3.1.1", "@types/gridfs-stream": "^0.5.35", "@types/json2csv": "^5.0.3", + "@types/nodemailer": "^6.4.7", "airtable": "^0.11.3", "axios": "^1.3.3", "bullmq": "^3.6.6", @@ -3872,6 +3873,14 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" }, + "node_modules/@types/nodemailer": { + "version": "6.4.7", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.7.tgz", + "integrity": "sha512-f5qCBGAn/f0qtRcd4SEn88c8Fp3Swct1731X4ryPKqS61/A3LmmzN8zaEz7hneJvpjFbUUgY7lru/B/7ODTazg==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/pg": { "version": "8.6.1", "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", @@ -13102,6 +13111,14 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" }, + "@types/nodemailer": { + "version": "6.4.7", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.7.tgz", + "integrity": "sha512-f5qCBGAn/f0qtRcd4SEn88c8Fp3Swct1731X4ryPKqS61/A3LmmzN8zaEz7hneJvpjFbUUgY7lru/B/7ODTazg==", + "requires": { + "@types/node": "*" + } + }, "@types/pg": { "version": "8.6.1", "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", diff --git a/CommonServer/package.json b/CommonServer/package.json index 195773e0f9..5137e98faa 100644 --- a/CommonServer/package.json +++ b/CommonServer/package.json @@ -18,6 +18,7 @@ "@types/ejs": "^3.1.1", "@types/gridfs-stream": "^0.5.35", "@types/json2csv": "^5.0.3", + "@types/nodemailer": "^6.4.7", "airtable": "^0.11.3", "axios": "^1.3.3", "bullmq": "^3.6.6", diff --git a/CommonUI/src/Components/Workflow/Utils.ts b/CommonUI/src/Components/Workflow/Utils.ts index 2633c4cc89..0f387ac8e8 100644 --- a/CommonUI/src/Components/Workflow/Utils.ts +++ b/CommonUI/src/Components/Workflow/Utils.ts @@ -60,6 +60,13 @@ export const componentInputTypeToFormFieldType: Function = ( }; } + if (componentInputType === ComponentInputType.HTML) { + return { + fieldType: FormFieldSchemaType.HTML, + dropdownOptions: [], + }; + } + if (componentInputType === ComponentInputType.CronTab) { return { fieldType: FormFieldSchemaType.Dropdown, From b1a85d874e1e4aed0e5b7c7a5ea98398cbe3264b Mon Sep 17 00:00:00 2001 From: Simon Larsen Date: Wed, 1 Mar 2023 20:14:11 +0000 Subject: [PATCH 06/11] add if else --- Common/Types/Workflow/ComponentID.ts | 3 +- Common/Types/Workflow/Components/Condition.ts | 97 +---------------- .../Workflow/Components/Conditions/IfElse.ts | 103 ++++++++++++++++++ .../Types/Workflow/Components/Index.ts | 5 + 4 files changed, 116 insertions(+), 92 deletions(-) create mode 100644 CommonServer/Types/Workflow/Components/Conditions/IfElse.ts diff --git a/Common/Types/Workflow/ComponentID.ts b/Common/Types/Workflow/ComponentID.ts index 455d7adabc..f9198b1682 100644 --- a/Common/Types/Workflow/ComponentID.ts +++ b/Common/Types/Workflow/ComponentID.ts @@ -11,7 +11,8 @@ enum ComponentID { ApiPut = 'api-get', ApiPost = 'api-get', ApiDelete = 'api-get', - SendEmail = 'send-email' + SendEmail = 'send-email', + IfElse = 'if-else' } export default ComponentID; diff --git a/Common/Types/Workflow/Components/Condition.ts b/Common/Types/Workflow/Components/Condition.ts index b83e1d423f..b7888d4dd5 100644 --- a/Common/Types/Workflow/Components/Condition.ts +++ b/Common/Types/Workflow/Components/Condition.ts @@ -1,4 +1,5 @@ import IconProp from '../../Icon/IconProp'; +import ComponentID from '../ComponentID'; import ComponentMetadata, { ComponentInputType, ComponentType, @@ -6,87 +7,7 @@ import ComponentMetadata, { const components: Array = [ { - id: 'if-true', - title: 'If True', - category: 'Conditions', - description: 'If the inputs are true then proceed', - iconProp: IconProp.Check, - componentType: ComponentType.Component, - arguments: [ - { - type: ComponentInputType.Text, - name: 'Expression 1', - description: 'Expression 1', - required: true, - id: 'expression-1', - }, - { - type: ComponentInputType.Text, - name: 'Expression 2', - description: 'Expression 2', - required: true, - id: 'expression-2', - }, - ], - returnValues: [], - inPorts: [ - { - title: 'In', - description: - 'Please connect components to this port for this component to work.', - id: 'in', - }, - ], - outPorts: [ - { - title: 'Yes', - description: 'If, yes then this port will be executed', - id: 'yes', - }, - ], - }, - { - id: 'if-false', - title: 'If False', - category: 'Conditions', - description: 'If the inputs are false then proceed', - iconProp: IconProp.Close, - componentType: ComponentType.Component, - arguments: [ - { - type: ComponentInputType.Text, - name: 'Expression 1', - description: 'Expression 1', - required: true, - id: 'expression-1', - }, - { - type: ComponentInputType.Text, - name: 'Expression 2', - description: 'Expression 2', - required: true, - id: 'expression-2', - }, - ], - returnValues: [], - inPorts: [ - { - title: 'In', - description: - 'Please connect components to this port for this component to work.', - id: 'in', - }, - ], - outPorts: [ - { - title: 'Yes', - description: 'If, yes then this port will be executed', - id: 'yes', - }, - ], - }, - { - id: 'if-else', + id: ComponentID.IfElse, title: 'If / Else', category: 'Conditions', description: 'Branch based on Inputs', @@ -95,17 +16,11 @@ const components: Array = [ arguments: [ { type: ComponentInputType.Text, - name: 'Expression 1', - description: 'Expression 1', + name: 'Expression', + description: 'Expression', + placeholder: "x === y", required: true, - id: 'expression-1', - }, - { - type: ComponentInputType.Text, - name: 'Expression 2', - description: 'Expression 2', - required: true, - id: 'expression-2', + id: 'expression', }, ], returnValues: [], diff --git a/CommonServer/Types/Workflow/Components/Conditions/IfElse.ts b/CommonServer/Types/Workflow/Components/Conditions/IfElse.ts new file mode 100644 index 0000000000..28bd1472c7 --- /dev/null +++ b/CommonServer/Types/Workflow/Components/Conditions/IfElse.ts @@ -0,0 +1,103 @@ +import BadDataException from 'Common/Types/Exception/BadDataException'; +import { JSONObject, JSONValue } from 'Common/Types/JSON'; +import ComponentMetadata, { Port } from 'Common/Types/Workflow/Component'; +import ComponentID from 'Common/Types/Workflow/ComponentID'; +import Components from 'Common/Types/Workflow/Components/Condition'; +import ComponentCode, { RunOptions, RunReturnType } from '../../ComponentCode'; +import VM, { VMScript } from 'vm2'; + +export default class IfElse extends ComponentCode { + public constructor() { + super(); + + const Component: ComponentMetadata | undefined = + Components.find((i: ComponentMetadata) => { + return i.id === ComponentID.IfElse; + }); + + if (!Component) { + throw new BadDataException( + 'Custom JavaScirpt Component not found.' + ); + } + + this.setMetadata(Component); + } + + public override async run( + args: JSONObject, + options: RunOptions + ): Promise { + const yesPort: Port | undefined = this.getMetadata().outPorts.find( + (p: Port) => { + return p.id === 'yes'; + } + ); + + if (!yesPort) { + throw options.onError( + new BadDataException('Yes port not found') + ); + } + + const noPort: Port | undefined = this.getMetadata().outPorts.find( + (p: Port) => { + return p.id === 'no'; + } + ); + + if (!noPort) { + throw options.onError(new BadDataException('No port not found')); + } + + try { + // Set timeout + // Inject args + // Inject dependencies + + const vm: VM.NodeVM = new VM.NodeVM({ + timeout: 5000, + allowAsync: true, + sandbox: { + args: args['arguments'], + console: { + log: (logValue: JSONValue) => { + options.log(logValue); + }, + }, + }, + }); + + const script: VMScript = new VMScript( + `module.exports = async function() { return ${(args['expression'] as string) || '' + } }` + ).compile(); + + const functionToRun: any = vm.run(script); + + const returnVal: any = await functionToRun(); + + if (returnVal) { + return { + returnValues: { + + }, + executePort: yesPort, + }; + } else { + return { + returnValues: { + + }, + executePort: noPort, + }; + } + } catch (err: any) { + options.log('Error running script'); + options.log( + err.message ? err.message : JSON.stringify(err, null, 2) + ); + throw options.onError(err); + } + } +} diff --git a/CommonServer/Types/Workflow/Components/Index.ts b/CommonServer/Types/Workflow/Components/Index.ts index f0b195c252..bb67bdeae4 100644 --- a/CommonServer/Types/Workflow/Components/Index.ts +++ b/CommonServer/Types/Workflow/Components/Index.ts @@ -27,6 +27,8 @@ import ApiGet from './API/Get'; import ApiDelete from './API/Delete'; import ApiPost from './API/Post'; import ApiPut from './API/Put'; +import Email from './Email'; +import IfElse from './Conditions/IfElse'; const Components: Dictionary = { [ComponentID.Webhook]: new WebhookTrigger(), @@ -41,6 +43,9 @@ const Components: Dictionary = { [ComponentID.ApiPost]: new ApiDelete(), [ComponentID.ApiDelete]: new ApiPost(), [ComponentID.ApiPut]: new ApiPut(), + [ComponentID.SendEmail]: new Email(), + [ComponentID.IfElse]: new IfElse() + }; From d63eb543795fff9cffad4b09b35eed277de196c6 Mon Sep 17 00:00:00 2001 From: Simon Larsen Date: Wed, 1 Mar 2023 20:29:14 +0000 Subject: [PATCH 07/11] fix lint --- Common/Types/Workflow/Component.ts | 2 +- Common/Types/Workflow/ComponentID.ts | 2 +- Common/Types/Workflow/Components/API.ts | 36 +++++--- Common/Types/Workflow/Components/BaseModel.ts | 19 +++-- Common/Types/Workflow/Components/Condition.ts | 2 +- Common/Types/Workflow/Components/Email.ts | 4 +- .../Types/Workflow/Components/API/Delete.ts | 20 +++-- .../Types/Workflow/Components/API/Get.ts | 20 +++-- .../Types/Workflow/Components/API/Post.ts | 20 +++-- .../Types/Workflow/Components/API/Put.ts | 20 +++-- .../Types/Workflow/Components/API/Utils.ts | 83 ++++++++++--------- .../Workflow/Components/Conditions/IfElse.ts | 29 +++---- .../Types/Workflow/Components/Email.ts | 60 ++++++-------- .../Types/Workflow/Components/Index.ts | 4 +- .../Workflow/Components/JSON/JsonToText.ts | 15 ++-- .../Workflow/Components/JSON/MergeJson.ts | 17 ++-- .../Workflow/Components/JSON/TextToJson.ts | 11 +-- .../src/Components/CodeEditor/CodeEditor.tsx | 11 +-- 18 files changed, 186 insertions(+), 189 deletions(-) diff --git a/Common/Types/Workflow/Component.ts b/Common/Types/Workflow/Component.ts index 07dd3e8908..c2f8208c39 100644 --- a/Common/Types/Workflow/Component.ts +++ b/Common/Types/Workflow/Component.ts @@ -22,7 +22,7 @@ export enum ComponentInputType { BaseModelArray = 'Database Records', JSONArray = 'List of JSON', LongText = 'Long Text', - HTML = 'HTML' + HTML = 'HTML', } export enum ComponentType { diff --git a/Common/Types/Workflow/ComponentID.ts b/Common/Types/Workflow/ComponentID.ts index f9198b1682..6d6e408431 100644 --- a/Common/Types/Workflow/ComponentID.ts +++ b/Common/Types/Workflow/ComponentID.ts @@ -12,7 +12,7 @@ enum ComponentID { ApiPost = 'api-get', ApiDelete = 'api-get', SendEmail = 'send-email', - IfElse = 'if-else' + IfElse = 'if-else', } export default ComponentID; diff --git a/Common/Types/Workflow/Components/API.ts b/Common/Types/Workflow/Components/API.ts index 604e60aa1f..4335818c2d 100644 --- a/Common/Types/Workflow/Components/API.ts +++ b/Common/Types/Workflow/Components/API.ts @@ -28,7 +28,8 @@ const components: Array = [ description: 'Request Body in JSON', type: ComponentInputType.JSON, required: false, - placeholder: 'Example: {"key1": "value1", "key2": "value2", ....}', + placeholder: + 'Example: {"key1": "value1", "key2": "value2", ....}', }, { id: 'query-string', @@ -37,7 +38,8 @@ const components: Array = [ type: ComponentInputType.StringDictionary, required: false, isAdvanced: true, - placeholder: 'Example: {"query1": "value1", "query2": "value2", ....}', + placeholder: + 'Example: {"query1": "value1", "query2": "value2", ....}', }, { id: 'request-headers', @@ -46,7 +48,8 @@ const components: Array = [ type: ComponentInputType.StringDictionary, required: false, isAdvanced: true, - placeholder: 'Example: {"header1": "value1", "header2": "value2", ....}', + placeholder: + 'Example: {"header1": "value1", "header2": "value2", ....}', }, ], returnValues: [ @@ -123,7 +126,8 @@ const components: Array = [ description: 'Request Body in JSON', type: ComponentInputType.JSON, required: false, - placeholder: 'Example: {"key1": "value1", "key2": "value2", ....}', + placeholder: + 'Example: {"key1": "value1", "key2": "value2", ....}', }, { id: 'query-string', @@ -132,7 +136,8 @@ const components: Array = [ type: ComponentInputType.StringDictionary, required: false, isAdvanced: true, - placeholder: 'Example: {"query1": "value1", "query2": "value2", ....}', + placeholder: + 'Example: {"query1": "value1", "query2": "value2", ....}', }, { id: 'request-headers', @@ -141,7 +146,8 @@ const components: Array = [ type: ComponentInputType.StringDictionary, required: false, isAdvanced: true, - placeholder: 'Example: {"header1": "value1", "header2": "value2", ....}', + placeholder: + 'Example: {"header1": "value1", "header2": "value2", ....}', }, ], returnValues: [ @@ -218,7 +224,8 @@ const components: Array = [ description: 'Request Body in JSON', type: ComponentInputType.JSON, required: false, - placeholder: 'Example: {"key1": "value1", "key2": "value2", ....}', + placeholder: + 'Example: {"key1": "value1", "key2": "value2", ....}', }, { id: 'query-string', @@ -227,7 +234,8 @@ const components: Array = [ type: ComponentInputType.StringDictionary, required: false, isAdvanced: true, - placeholder: 'Example: {"query1": "value1", "query2": "value2", ....}', + placeholder: + 'Example: {"query1": "value1", "query2": "value2", ....}', }, { id: 'request-headers', @@ -236,7 +244,8 @@ const components: Array = [ type: ComponentInputType.StringDictionary, required: false, isAdvanced: true, - placeholder: 'Example: {"header1": "value1", "header2": "value2", ....}', + placeholder: + 'Example: {"header1": "value1", "header2": "value2", ....}', }, ], returnValues: [ @@ -313,7 +322,8 @@ const components: Array = [ description: 'Request Body in JSON', type: ComponentInputType.JSON, required: false, - placeholder: 'Example: {"key1": "value1", "key2": "value2", ....}', + placeholder: + 'Example: {"key1": "value1", "key2": "value2", ....}', }, { id: 'query-string', @@ -322,7 +332,8 @@ const components: Array = [ type: ComponentInputType.StringDictionary, required: false, isAdvanced: true, - placeholder: 'Example: {"query1": "value1", "query2": "value2", ....}', + placeholder: + 'Example: {"query1": "value1", "query2": "value2", ....}', }, { id: 'request-headers', @@ -331,7 +342,8 @@ const components: Array = [ type: ComponentInputType.StringDictionary, required: false, isAdvanced: true, - placeholder: 'Example: {"header1": "value1", "header2": "value2", ....}', + placeholder: + 'Example: {"header1": "value1", "header2": "value2", ....}', }, ], returnValues: [ diff --git a/Common/Types/Workflow/Components/BaseModel.ts b/Common/Types/Workflow/Components/BaseModel.ts index 65c0c2376c..003ff351b2 100644 --- a/Common/Types/Workflow/Components/BaseModel.ts +++ b/Common/Types/Workflow/Components/BaseModel.ts @@ -30,7 +30,7 @@ export default class BaseModelComponent { description: `Query on ${model.singularName}`, required: true, id: 'query', - placeholder: "Example: {'columnName': 'value', ...}" + placeholder: "Example: {'columnName': 'value', ...}", }, { type: ComponentInputType.Query, @@ -38,7 +38,7 @@ export default class BaseModelComponent { description: `Select on ${model.singularName}`, required: true, id: 'select', - placeholder: "Example: {'columnName': true, ...}" + placeholder: "Example: {'columnName': true, ...}", }, ], returnValues: [ @@ -89,7 +89,7 @@ export default class BaseModelComponent { description: 'Please fill out this query', required: true, id: 'query', - placeholder: "Example: {'columnName': 'value', ...}" + placeholder: "Example: {'columnName': 'value', ...}", }, { type: ComponentInputType.Query, @@ -97,7 +97,7 @@ export default class BaseModelComponent { description: `Select on ${model.singularName}`, required: true, id: 'select', - placeholder: "Example: {'columnName': true, ...}" + placeholder: "Example: {'columnName': true, ...}", }, { type: ComponentInputType.Number, @@ -193,7 +193,7 @@ export default class BaseModelComponent { description: 'Please fill out this query', required: true, id: 'query', - placeholder: "Example: {'columnName': 'value', ...}" + placeholder: "Example: {'columnName': 'value', ...}", }, ], returnValues: [], @@ -236,7 +236,7 @@ export default class BaseModelComponent { description: 'Please fill out this query', required: true, id: 'query', - placeholder: "Example: {'columnName': 'value', ...}" + placeholder: "Example: {'columnName': 'value', ...}", }, { type: ComponentInputType.Number, @@ -372,7 +372,8 @@ export default class BaseModelComponent { { id: 'json-array', name: 'JSON Array', - placeholder: "Example: [{'columnName': 'value', ...}, {...}]", + placeholder: + "Example: [{'columnName': 'value', ...}, {...}]", description: 'List of models represented as JSON array', type: ComponentInputType.JSONArray, required: true, @@ -456,7 +457,7 @@ export default class BaseModelComponent { description: 'Please fill out this query', required: true, id: 'query', - placeholder: "Example: {'columnName': 'value', ...}" + placeholder: "Example: {'columnName': 'value', ...}", }, { id: 'data', @@ -507,7 +508,7 @@ export default class BaseModelComponent { description: 'Please fill out this query', required: true, id: 'query', - placeholder: "Example: {'columnName': 'value', ...}" + placeholder: "Example: {'columnName': 'value', ...}", }, { id: 'data', diff --git a/Common/Types/Workflow/Components/Condition.ts b/Common/Types/Workflow/Components/Condition.ts index b7888d4dd5..50b4271567 100644 --- a/Common/Types/Workflow/Components/Condition.ts +++ b/Common/Types/Workflow/Components/Condition.ts @@ -18,7 +18,7 @@ const components: Array = [ type: ComponentInputType.Text, name: 'Expression', description: 'Expression', - placeholder: "x === y", + placeholder: 'x === y', required: true, id: 'expression', }, diff --git a/Common/Types/Workflow/Components/Email.ts b/Common/Types/Workflow/Components/Email.ts index f95539d3b8..daf22d3cde 100644 --- a/Common/Types/Workflow/Components/Email.ts +++ b/Common/Types/Workflow/Components/Email.ts @@ -18,7 +18,7 @@ const components: Array = [ type: ComponentInputType.Text, name: 'From Email', description: 'Email to send from', - placeholder: "Name ", + placeholder: 'Name ', required: true, id: 'from', }, @@ -26,7 +26,7 @@ const components: Array = [ type: ComponentInputType.Text, name: 'To Email', description: 'Email to send to', - placeholder: "email@company.com; email2@company.com; ...", + placeholder: 'email@company.com; email2@company.com; ...', required: true, id: 'to', }, diff --git a/CommonServer/Types/Workflow/Components/API/Delete.ts b/CommonServer/Types/Workflow/Components/API/Delete.ts index 7cdd703e3c..1d9f253f75 100644 --- a/CommonServer/Types/Workflow/Components/API/Delete.ts +++ b/CommonServer/Types/Workflow/Components/API/Delete.ts @@ -33,22 +33,24 @@ export default class ApiDelete extends ComponentCode { args: JSONObject, options: RunOptions ): Promise { + const result: { args: JSONObject; successPort: Port; errorPort: Port } = + ApiComponentUtils.sanitizeArgs(this.getMetadata(), args, options); - const result: { args: JSONObject, successPort: Port, errorPort: Port } = ApiComponentUtils.sanitizeArgs(this.getMetadata(), args, options); - - let apiResult: HTTPResponse | HTTPErrorResponse | null = null; + let apiResult: HTTPResponse | HTTPErrorResponse | null = + null; try { - - apiResult = await API.delete(args['url'] as URL, args['request-body'] as JSONObject, args['request-headers'] as Dictionary); + apiResult = await API.delete( + args['url'] as URL, + args['request-body'] as JSONObject, + args['request-headers'] as Dictionary + ); return Promise.resolve({ returnValues: ApiComponentUtils.getReturnValues(apiResult), executePort: result.successPort, }); - } catch (err) { - if (err instanceof HTTPErrorResponse) { return Promise.resolve({ returnValues: ApiComponentUtils.getReturnValues(err), @@ -63,7 +65,9 @@ export default class ApiDelete extends ComponentCode { }); } - throw options.onError(new APIException("Something wrong happened.")); + throw options.onError( + new APIException('Something wrong happened.') + ); } } } diff --git a/CommonServer/Types/Workflow/Components/API/Get.ts b/CommonServer/Types/Workflow/Components/API/Get.ts index de82fab84c..d1a18ff63a 100644 --- a/CommonServer/Types/Workflow/Components/API/Get.ts +++ b/CommonServer/Types/Workflow/Components/API/Get.ts @@ -33,22 +33,24 @@ export default class ApiGet extends ComponentCode { args: JSONObject, options: RunOptions ): Promise { + const result: { args: JSONObject; successPort: Port; errorPort: Port } = + ApiComponentUtils.sanitizeArgs(this.getMetadata(), args, options); - const result: { args: JSONObject, successPort: Port, errorPort: Port } = ApiComponentUtils.sanitizeArgs(this.getMetadata(), args, options); - - let apiResult: HTTPResponse | HTTPErrorResponse | null = null; + let apiResult: HTTPResponse | HTTPErrorResponse | null = + null; try { - - apiResult = await API.get(args['url'] as URL, args['request-body'] as JSONObject, args['request-headers'] as Dictionary); + apiResult = await API.get( + args['url'] as URL, + args['request-body'] as JSONObject, + args['request-headers'] as Dictionary + ); return Promise.resolve({ returnValues: ApiComponentUtils.getReturnValues(apiResult), executePort: result.successPort, }); - } catch (err) { - if (err instanceof HTTPErrorResponse) { return Promise.resolve({ returnValues: ApiComponentUtils.getReturnValues(err), @@ -63,7 +65,9 @@ export default class ApiGet extends ComponentCode { }); } - throw options.onError(new APIException("Something wrong happened.")); + throw options.onError( + new APIException('Something wrong happened.') + ); } } } diff --git a/CommonServer/Types/Workflow/Components/API/Post.ts b/CommonServer/Types/Workflow/Components/API/Post.ts index d296f6ea5a..c5c0c68121 100644 --- a/CommonServer/Types/Workflow/Components/API/Post.ts +++ b/CommonServer/Types/Workflow/Components/API/Post.ts @@ -33,22 +33,24 @@ export default class ApiPost extends ComponentCode { args: JSONObject, options: RunOptions ): Promise { + const result: { args: JSONObject; successPort: Port; errorPort: Port } = + ApiComponentUtils.sanitizeArgs(this.getMetadata(), args, options); - const result: { args: JSONObject, successPort: Port, errorPort: Port } = ApiComponentUtils.sanitizeArgs(this.getMetadata(), args, options); - - let apiResult: HTTPResponse | HTTPErrorResponse | null = null; + let apiResult: HTTPResponse | HTTPErrorResponse | null = + null; try { - - apiResult = await API.post(args['url'] as URL, args['request-body'] as JSONObject, args['request-headers'] as Dictionary); + apiResult = await API.post( + args['url'] as URL, + args['request-body'] as JSONObject, + args['request-headers'] as Dictionary + ); return Promise.resolve({ returnValues: ApiComponentUtils.getReturnValues(apiResult), executePort: result.successPort, }); - } catch (err) { - if (err instanceof HTTPErrorResponse) { return Promise.resolve({ returnValues: ApiComponentUtils.getReturnValues(err), @@ -63,7 +65,9 @@ export default class ApiPost extends ComponentCode { }); } - throw options.onError(new APIException("Something wrong happened.")); + throw options.onError( + new APIException('Something wrong happened.') + ); } } } diff --git a/CommonServer/Types/Workflow/Components/API/Put.ts b/CommonServer/Types/Workflow/Components/API/Put.ts index ce4fc72c81..031ff40607 100644 --- a/CommonServer/Types/Workflow/Components/API/Put.ts +++ b/CommonServer/Types/Workflow/Components/API/Put.ts @@ -33,22 +33,24 @@ export default class ApiPut extends ComponentCode { args: JSONObject, options: RunOptions ): Promise { + const result: { args: JSONObject; successPort: Port; errorPort: Port } = + ApiComponentUtils.sanitizeArgs(this.getMetadata(), args, options); - const result: { args: JSONObject, successPort: Port, errorPort: Port } = ApiComponentUtils.sanitizeArgs(this.getMetadata(), args, options); - - let apiResult: HTTPResponse | HTTPErrorResponse | null = null; + let apiResult: HTTPResponse | HTTPErrorResponse | null = + null; try { - - apiResult = await API.put(args['url'] as URL, args['request-body'] as JSONObject, args['request-headers'] as Dictionary); + apiResult = await API.put( + args['url'] as URL, + args['request-body'] as JSONObject, + args['request-headers'] as Dictionary + ); return Promise.resolve({ returnValues: ApiComponentUtils.getReturnValues(apiResult), executePort: result.successPort, }); - } catch (err) { - if (err instanceof HTTPErrorResponse) { return Promise.resolve({ returnValues: ApiComponentUtils.getReturnValues(err), @@ -63,7 +65,9 @@ export default class ApiPut extends ComponentCode { }); } - throw options.onError(new APIException("Something wrong happened.")); + throw options.onError( + new APIException('Something wrong happened.') + ); } } } diff --git a/CommonServer/Types/Workflow/Components/API/Utils.ts b/CommonServer/Types/Workflow/Components/API/Utils.ts index cf73b77b82..c75eb3b16e 100644 --- a/CommonServer/Types/Workflow/Components/API/Utils.ts +++ b/CommonServer/Types/Workflow/Components/API/Utils.ts @@ -1,36 +1,37 @@ -import BadDataException from "Common/Types/Exception/BadDataException"; -import { JSONObject } from "Common/Types/JSON"; -import ComponentMetadata, { Port } from "Common/Types/Workflow/Component"; -import { RunOptions } from "../../ComponentCode"; -import URL from "Common/Types/API/URL"; -import HTTPResponse from "Common/Types/API/HTTPResponse"; -import HTTPErrorResponse from "Common/Types/API/HTTPErrorResponse"; +import BadDataException from 'Common/Types/Exception/BadDataException'; +import { JSONObject } from 'Common/Types/JSON'; +import ComponentMetadata, { Port } from 'Common/Types/Workflow/Component'; +import { RunOptions } from '../../ComponentCode'; +import URL from 'Common/Types/API/URL'; +import HTTPResponse from 'Common/Types/API/HTTPResponse'; +import HTTPErrorResponse from 'Common/Types/API/HTTPErrorResponse'; -export class ApiComponentUtils { - - - public static getReturnValues(response: HTTPResponse | HTTPErrorResponse): JSONObject { - - - if(response instanceof HTTPErrorResponse){ +export class ApiComponentUtils { + public static getReturnValues( + response: HTTPResponse | HTTPErrorResponse + ): JSONObject { + if (response instanceof HTTPErrorResponse) { return { - "response-status": response.statusCode, - "response-body": response.jsonData, - "response-headers": response.headers, - "error": response.message || "Server Error." - } + 'response-status': response.statusCode, + 'response-body': response.jsonData, + 'response-headers': response.headers, + error: response.message || 'Server Error.', + }; } return { - "response-status": response.statusCode, - "response-body": response.jsonData, - "response-headers": response.headers, - "error": null - } - } + 'response-status': response.statusCode, + 'response-body': response.jsonData, + 'response-headers': response.headers, + error: null, + }; + } - public static sanitizeArgs(metadata: ComponentMetadata, args: JSONObject, - options: RunOptions): {args: JSONObject, successPort: Port, errorPort: Port} { + public static sanitizeArgs( + metadata: ComponentMetadata, + args: JSONObject, + options: RunOptions + ): { args: JSONObject; successPort: Port; errorPort: Port } { const successPort: Port | undefined = metadata.outPorts.find( (p: Port) => { return p.id === 'success'; @@ -53,35 +54,35 @@ export class ApiComponentUtils { throw options.onError(new BadDataException('Error port not found')); } - if (args['request-body'] && typeof args['request-body'] === 'string') { args['request-body'] = JSON.parse(args['request-body'] as string); - } if (args['query-string'] && typeof args['query-string'] === 'string') { args['query-string'] = JSON.parse(args['query-string'] as string); - } - if (args['request-headers'] && typeof args['request-headers'] === 'string') { - args['request-headers'] = JSON.parse(args['request-headers'] as string); - } - - if(!args['url']){ - throw options.onError( - new BadDataException('URL not found') + if ( + args['request-headers'] && + typeof args['request-headers'] === 'string' + ) { + args['request-headers'] = JSON.parse( + args['request-headers'] as string ); } - if(args['url'] && typeof args["url"] !== "string"){ + if (!args['url']) { + throw options.onError(new BadDataException('URL not found')); + } + + if (args['url'] && typeof args['url'] !== 'string') { throw options.onError( new BadDataException('URL is not type of string') ); } - args['url'] = URL.fromString(args["url"] as string); + args['url'] = URL.fromString(args['url'] as string); - return {args, successPort, errorPort}; + return { args, successPort, errorPort }; } -} \ No newline at end of file +} diff --git a/CommonServer/Types/Workflow/Components/Conditions/IfElse.ts b/CommonServer/Types/Workflow/Components/Conditions/IfElse.ts index 28bd1472c7..6dde987196 100644 --- a/CommonServer/Types/Workflow/Components/Conditions/IfElse.ts +++ b/CommonServer/Types/Workflow/Components/Conditions/IfElse.ts @@ -10,10 +10,11 @@ export default class IfElse extends ComponentCode { public constructor() { super(); - const Component: ComponentMetadata | undefined = - Components.find((i: ComponentMetadata) => { + const Component: ComponentMetadata | undefined = Components.find( + (i: ComponentMetadata) => { return i.id === ComponentID.IfElse; - }); + } + ); if (!Component) { throw new BadDataException( @@ -35,9 +36,7 @@ export default class IfElse extends ComponentCode { ); if (!yesPort) { - throw options.onError( - new BadDataException('Yes port not found') - ); + throw options.onError(new BadDataException('Yes port not found')); } const noPort: Port | undefined = this.getMetadata().outPorts.find( @@ -69,7 +68,8 @@ export default class IfElse extends ComponentCode { }); const script: VMScript = new VMScript( - `module.exports = async function() { return ${(args['expression'] as string) || '' + `module.exports = async function() { return ${ + (args['expression'] as string) || '' } }` ).compile(); @@ -79,19 +79,14 @@ export default class IfElse extends ComponentCode { if (returnVal) { return { - returnValues: { - - }, + returnValues: {}, executePort: yesPort, }; - } else { - return { - returnValues: { - - }, - executePort: noPort, - }; } + return { + returnValues: {}, + executePort: noPort, + }; } catch (err: any) { options.log('Error running script'); options.log( diff --git a/CommonServer/Types/Workflow/Components/Email.ts b/CommonServer/Types/Workflow/Components/Email.ts index dd91a496e3..25aca71d91 100644 --- a/CommonServer/Types/Workflow/Components/Email.ts +++ b/CommonServer/Types/Workflow/Components/Email.ts @@ -27,8 +27,6 @@ export default class Email extends ComponentCode { args: JSONObject, options: RunOptions ): Promise { - - const successPort: Port | undefined = this.getMetadata().outPorts.find( (p: Port) => { return p.id === 'success'; @@ -52,93 +50,84 @@ export default class Email extends ComponentCode { } if (!args['to']) { - throw options.onError( - new BadDataException('to not found') - ); + throw options.onError(new BadDataException('to not found')); } - if (args['to'] && typeof args["to"] !== "string") { + if (args['to'] && typeof args['to'] !== 'string') { throw options.onError( new BadDataException('to is not type of string') ); } if (!args['from']) { - throw options.onError( - new BadDataException('from not found') - ); + throw options.onError(new BadDataException('from not found')); } - if (args['from'] && typeof args["from"] !== "string") { + if (args['from'] && typeof args['from'] !== 'string') { throw options.onError( new BadDataException('from is not type of string') ); } - if (!args['smtp-username']) { - throw options.onError( - new BadDataException('email not found') - ); + throw options.onError(new BadDataException('email not found')); } - if (args['smtp-username'] && typeof args["smtp-username"] !== "string") { + if ( + args['smtp-username'] && + typeof args['smtp-username'] !== 'string' + ) { throw options.onError( new BadDataException('smtp-username is not type of string') ); } - if (!args['smtp-password']) { - throw options.onError( - new BadDataException('email not found') - ); + throw options.onError(new BadDataException('email not found')); } - if (args['smtp-password'] && typeof args["smtp-password"] !== "string") { + if ( + args['smtp-password'] && + typeof args['smtp-password'] !== 'string' + ) { throw options.onError( new BadDataException('smtp-username is not type of string') ); } if (!args['smtp-host']) { - throw options.onError( - new BadDataException('email not found') - ); + throw options.onError(new BadDataException('email not found')); } - if (args['smtp-host'] && typeof args["smtp-host"] !== "string") { + if (args['smtp-host'] && typeof args['smtp-host'] !== 'string') { throw options.onError( new BadDataException('smtp-host is not type of string') ); } if (!args['smtp-port']) { - throw options.onError( - new BadDataException('email not found') - ); + throw options.onError(new BadDataException('email not found')); } - if (args['smtp-port'] && typeof args["smtp-port"] === "string") { + if (args['smtp-port'] && typeof args['smtp-port'] === 'string') { args['smtp-port'] = parseInt(args['smtp-port']); } - if (args['smtp-port'] && typeof args["smtp-port"] !== "number") { + if (args['smtp-port'] && typeof args['smtp-port'] !== 'number') { throw options.onError( new BadDataException('smtp-host is not type of number') ); } try { - const mailer: Transporter = nodemailer.createTransport({ host: args['smtp-host']?.toString(), port: args['smtp-port'] as number, - secure: !!args['secure'], + secure: Boolean(args['secure']), auth: { user: args['smtp-username'] as string, pass: args['smtp-password'] as string, - } + }, }); await mailer.sendMail({ @@ -148,15 +137,14 @@ export default class Email extends ComponentCode { html: args['body']?.toString() || '', }); - options.log("Email sent."); - + options.log('Email sent.'); + return Promise.resolve({ returnValues: {}, executePort: successPort, }); - } catch (err) { - options.log(err); + options.log(err); return Promise.resolve({ returnValues: {}, executePort: successPort, diff --git a/CommonServer/Types/Workflow/Components/Index.ts b/CommonServer/Types/Workflow/Components/Index.ts index bb67bdeae4..972103e2d2 100644 --- a/CommonServer/Types/Workflow/Components/Index.ts +++ b/CommonServer/Types/Workflow/Components/Index.ts @@ -44,9 +44,7 @@ const Components: Dictionary = { [ComponentID.ApiDelete]: new ApiPost(), [ComponentID.ApiPut]: new ApiPut(), [ComponentID.SendEmail]: new Email(), - [ComponentID.IfElse]: new IfElse() - - + [ComponentID.IfElse]: new IfElse(), }; for (const baseModelService of BaseModelServices) { diff --git a/CommonServer/Types/Workflow/Components/JSON/JsonToText.ts b/CommonServer/Types/Workflow/Components/JSON/JsonToText.ts index 0e17b4a5c9..1b9424a5c5 100644 --- a/CommonServer/Types/Workflow/Components/JSON/JsonToText.ts +++ b/CommonServer/Types/Workflow/Components/JSON/JsonToText.ts @@ -49,14 +49,11 @@ export default class JsonToText extends ComponentCode { } if (!args['json']) { - throw options.onError( - new BadDataException('JSON is undefined.') - ); + throw options.onError(new BadDataException('JSON is undefined.')); } if (typeof args['json'] === 'string') { args['json'] = JSON.parse(args['json'] as string); - } if (typeof args['json'] !== 'object') { @@ -66,17 +63,17 @@ export default class JsonToText extends ComponentCode { } try { - - const returnValue: string = JSON.stringify(args['json'] as JSONObject); + const returnValue: string = JSON.stringify( + args['json'] as JSONObject + ); return Promise.resolve({ returnValues: { - text: returnValue + text: returnValue, }, executePort: successPort, }); - } catch (err) { - options.log("JSON is not in the correct format."); + options.log('JSON is not in the correct format.'); return Promise.resolve({ returnValues: {}, executePort: errorPort, diff --git a/CommonServer/Types/Workflow/Components/JSON/MergeJson.ts b/CommonServer/Types/Workflow/Components/JSON/MergeJson.ts index 3127713dbb..e35bdb8331 100644 --- a/CommonServer/Types/Workflow/Components/JSON/MergeJson.ts +++ b/CommonServer/Types/Workflow/Components/JSON/MergeJson.ts @@ -49,14 +49,11 @@ export default class MergeJSON extends ComponentCode { } if (!args['json1']) { - throw options.onError( - new BadDataException('JSON1 is undefined.') - ); + throw options.onError(new BadDataException('JSON1 is undefined.')); } if (typeof args['json1'] === 'string') { args['json1'] = JSON.parse(args['json1'] as string); - } if (typeof args['json2'] !== 'object') { @@ -65,16 +62,12 @@ export default class MergeJSON extends ComponentCode { ); } - if (!args['json2']) { - throw options.onError( - new BadDataException('JSON2 is undefined.') - ); + throw options.onError(new BadDataException('JSON2 is undefined.')); } if (typeof args['json2'] === 'string') { args['json2'] = JSON.parse(args['json2'] as string); - } if (typeof args['json2'] !== 'object') { @@ -86,9 +79,9 @@ export default class MergeJSON extends ComponentCode { return Promise.resolve({ returnValues: { json: { - ...args['json1'] as JSONObject, - ...args['json2'] as JSONObject - } + ...(args['json1'] as JSONObject), + ...(args['json2'] as JSONObject), + }, }, executePort: successPort, }); diff --git a/CommonServer/Types/Workflow/Components/JSON/TextToJson.ts b/CommonServer/Types/Workflow/Components/JSON/TextToJson.ts index a54d5dabc5..162111d29f 100644 --- a/CommonServer/Types/Workflow/Components/JSON/TextToJson.ts +++ b/CommonServer/Types/Workflow/Components/JSON/TextToJson.ts @@ -49,12 +49,9 @@ export default class TextToJSON extends ComponentCode { } if (!args['text']) { - throw options.onError( - new BadDataException('text is undefined.') - ); + throw options.onError(new BadDataException('text is undefined.')); } - if (typeof args['text'] !== 'string') { throw options.onError( new BadDataException('text is should be of type string.') @@ -62,17 +59,15 @@ export default class TextToJSON extends ComponentCode { } try { - const returnValue: JSONObject = JSON.parse(args['text'] as string); return Promise.resolve({ returnValues: { - json: returnValue + json: returnValue, }, executePort: successPort, }); - } catch (err) { - options.log("text is not in the correct format."); + options.log('text is not in the correct format.'); return Promise.resolve({ returnValues: {}, executePort: errorPort, diff --git a/CommonUI/src/Components/CodeEditor/CodeEditor.tsx b/CommonUI/src/Components/CodeEditor/CodeEditor.tsx index 51ee4a0b39..006204c4ce 100644 --- a/CommonUI/src/Components/CodeEditor/CodeEditor.tsx +++ b/CommonUI/src/Components/CodeEditor/CodeEditor.tsx @@ -107,11 +107,12 @@ const CodeEditor: FunctionComponent = ( props.onFocus && props.onFocus(); }} > - - {helpText &&

{helpText}

} + {helpText && ( +

+ {' '} + {helpText}{' '} +

+ )} Date: Wed, 1 Mar 2023 21:00:27 +0000 Subject: [PATCH 08/11] fix email component --- CommonServer/Types/Workflow/Components/Email.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CommonServer/Types/Workflow/Components/Email.ts b/CommonServer/Types/Workflow/Components/Email.ts index 25aca71d91..81f83b9c7e 100644 --- a/CommonServer/Types/Workflow/Components/Email.ts +++ b/CommonServer/Types/Workflow/Components/Email.ts @@ -134,7 +134,7 @@ export default class Email extends ComponentCode { from: args['from'].toString(), to: args['to'].toString(), subject: args['subject']?.toString() || '', - html: args['body']?.toString() || '', + html: args['email-body']?.toString() || '', }); options.log('Email sent.'); From da9bd35ee6b1c4b5d72e7527e1608f7882d6a99c Mon Sep 17 00:00:00 2001 From: Simon Larsen Date: Wed, 1 Mar 2023 21:46:21 +0000 Subject: [PATCH 09/11] remove query string from api component. --- Common/Types/Workflow/ComponentID.ts | 6 +-- Common/Types/Workflow/Components/API.ts | 40 -------------- .../Types/Workflow/Components/API/Utils.ts | 4 -- .../Types/Workflow/Components/Index.ts | 4 +- Workflow/Services/RunWorkflow.ts | 54 ++++++++++++------- 5 files changed, 40 insertions(+), 68 deletions(-) diff --git a/Common/Types/Workflow/ComponentID.ts b/Common/Types/Workflow/ComponentID.ts index 6d6e408431..c8b8a8b65d 100644 --- a/Common/Types/Workflow/ComponentID.ts +++ b/Common/Types/Workflow/ComponentID.ts @@ -8,9 +8,9 @@ enum ComponentID { TextToJson = 'text-to-json', MergeJson = 'merge-json', ApiGet = 'api-get', - ApiPut = 'api-get', - ApiPost = 'api-get', - ApiDelete = 'api-get', + ApiPut = 'api-put', + ApiPost = 'api-post', + ApiDelete = 'api-delete', SendEmail = 'send-email', IfElse = 'if-else', } diff --git a/Common/Types/Workflow/Components/API.ts b/Common/Types/Workflow/Components/API.ts index 4335818c2d..9dd52cc4cf 100644 --- a/Common/Types/Workflow/Components/API.ts +++ b/Common/Types/Workflow/Components/API.ts @@ -31,16 +31,6 @@ const components: Array = [ placeholder: 'Example: {"key1": "value1", "key2": "value2", ....}', }, - { - id: 'query-string', - name: 'Query String', - description: 'Send query string params.', - type: ComponentInputType.StringDictionary, - required: false, - isAdvanced: true, - placeholder: - 'Example: {"query1": "value1", "query2": "value2", ....}', - }, { id: 'request-headers', name: 'Request Headers', @@ -129,16 +119,6 @@ const components: Array = [ placeholder: 'Example: {"key1": "value1", "key2": "value2", ....}', }, - { - id: 'query-string', - name: 'Query String', - description: 'Send query string params.', - type: ComponentInputType.StringDictionary, - required: false, - isAdvanced: true, - placeholder: - 'Example: {"query1": "value1", "query2": "value2", ....}', - }, { id: 'request-headers', name: 'Request Headers', @@ -227,16 +207,6 @@ const components: Array = [ placeholder: 'Example: {"key1": "value1", "key2": "value2", ....}', }, - { - id: 'query-string', - name: 'Query String', - description: 'Send query string params.', - type: ComponentInputType.StringDictionary, - required: false, - isAdvanced: true, - placeholder: - 'Example: {"query1": "value1", "query2": "value2", ....}', - }, { id: 'request-headers', name: 'Request Headers', @@ -325,16 +295,6 @@ const components: Array = [ placeholder: 'Example: {"key1": "value1", "key2": "value2", ....}', }, - { - id: 'query-string', - name: 'Query String', - description: 'Send query string params.', - type: ComponentInputType.StringDictionary, - required: false, - isAdvanced: true, - placeholder: - 'Example: {"query1": "value1", "query2": "value2", ....}', - }, { id: 'request-headers', name: 'Request Headers', diff --git a/CommonServer/Types/Workflow/Components/API/Utils.ts b/CommonServer/Types/Workflow/Components/API/Utils.ts index c75eb3b16e..bf079d0b62 100644 --- a/CommonServer/Types/Workflow/Components/API/Utils.ts +++ b/CommonServer/Types/Workflow/Components/API/Utils.ts @@ -58,10 +58,6 @@ export class ApiComponentUtils { args['request-body'] = JSON.parse(args['request-body'] as string); } - if (args['query-string'] && typeof args['query-string'] === 'string') { - args['query-string'] = JSON.parse(args['query-string'] as string); - } - if ( args['request-headers'] && typeof args['request-headers'] === 'string' diff --git a/CommonServer/Types/Workflow/Components/Index.ts b/CommonServer/Types/Workflow/Components/Index.ts index 972103e2d2..7a98ff1c95 100644 --- a/CommonServer/Types/Workflow/Components/Index.ts +++ b/CommonServer/Types/Workflow/Components/Index.ts @@ -40,8 +40,8 @@ const Components: Dictionary = { [ComponentID.MergeJson]: new MergeJSON(), [ComponentID.TextToJson]: new TextToJSON(), [ComponentID.ApiGet]: new ApiGet(), - [ComponentID.ApiPost]: new ApiDelete(), - [ComponentID.ApiDelete]: new ApiPost(), + [ComponentID.ApiPost]: new ApiPost(), + [ComponentID.ApiDelete]: new ApiDelete(), [ComponentID.ApiPut]: new ApiPut(), [ComponentID.SendEmail]: new Email(), [ComponentID.IfElse]: new IfElse(), diff --git a/Workflow/Services/RunWorkflow.ts b/Workflow/Services/RunWorkflow.ts index 828239b6f8..116c0a9e2c 100644 --- a/Workflow/Services/RunWorkflow.ts +++ b/Workflow/Services/RunWorkflow.ts @@ -158,8 +158,8 @@ export default class RunWorkflow { if (didWorkflowTimeOut) { throw new TimeoutException( 'Workflow execution time was more than ' + - runProps.timeout + - 'ms and workflow timed-out.' + runProps.timeout + + 'ms and workflow timed-out.' ); } @@ -171,8 +171,8 @@ export default class RunWorkflow { if (componentsExecuted.includes(executeComponentId)) { throw new BadDataException( 'Cyclic Workflow Detected. Cannot execute ' + - executeComponentId + - ' when it has already been executed.' + executeComponentId + + ' when it has already been executed.' ); } @@ -186,8 +186,8 @@ export default class RunWorkflow { if (!stackItem) { throw new BadDataException( 'Component with ID ' + - executeComponentId + - ' not found.' + executeComponentId + + ' not found.' ); } @@ -253,7 +253,7 @@ export default class RunWorkflow { this.log(result.returnValues); this.log( 'Executing Port: ' + result.executePort?.title || - '' + '' ); storageMap.local.components[stackItem.node.id] = { @@ -387,16 +387,32 @@ export default class RunWorkflow { argumentContent.toString().includes('{{') && argumentContent.toString().includes('}}') ) { - // this is dynamic content. Pick from storageMap. - argumentContent = argumentContent - .toString() - .replace('{{', '') - .replace('}}', ''); - argumentContent = deepFind( - storageMap as any, - argumentContent as any - ); + + + let argumentContentCopy = argumentContent.toString(); + const variablesInArgument = []; + + const regex = /{{(.*?)}}/g // Find all matches of the regular expression and capture the word between the braces {{x}} => x + + + let match; + + while ((match = regex.exec(argumentContentCopy)) !== null) { + variablesInArgument.push(match[1]); + } + + for(const variable of variablesInArgument){ + + const value = deepFind( + storageMap as any, + variable as any + ); + + argumentContentCopy = argumentContentCopy.replace("{{"+variable+"}}", value); + } + + argumentContent = argumentContentCopy; } argumentObj[argument.id] = argumentContent; @@ -515,8 +531,8 @@ export default class RunWorkflow { } else { this.logs.push( OneUptimeDate.getCurrentDateAsFormattedString() + - ': ' + - JSON.stringify(data) + ': ' + + JSON.stringify(data) ); } } @@ -590,7 +606,7 @@ export default class RunWorkflow { const trigger: any | undefined = nodes.find((n: any) => { return ( (n.data as NodeDataProp).componentType === - ComponentType.Trigger && + ComponentType.Trigger && (n.data as NodeDataProp).nodeType === NodeType.Node ); }); From 93cbac33fb7b2576861805cd81622810b5cb37ac Mon Sep 17 00:00:00 2001 From: Simon Larsen Date: Wed, 1 Mar 2023 22:15:25 +0000 Subject: [PATCH 10/11] fix bugs --- Common/Types/Workflow/Components/JSON.ts | 6 ++++++ CommonServer/Infrastructure/Queue.ts | 5 +++++ CommonServer/Types/Workflow/Components/JSON/MergeJson.ts | 4 ++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Common/Types/Workflow/Components/JSON.ts b/Common/Types/Workflow/Components/JSON.ts index 169f2623a9..fa49c08266 100644 --- a/Common/Types/Workflow/Components/JSON.ts +++ b/Common/Types/Workflow/Components/JSON.ts @@ -149,6 +149,12 @@ const components: Array = [ 'This is executed when the JSON is successfully merged', id: 'success', }, + { + title: 'Error', + description: + 'This is executed when the JSON is not successfully merged', + id: 'error', + }, ], }, ]; diff --git a/CommonServer/Infrastructure/Queue.ts b/CommonServer/Infrastructure/Queue.ts index 5497bbd084..0f33a9ed2a 100644 --- a/CommonServer/Infrastructure/Queue.ts +++ b/CommonServer/Infrastructure/Queue.ts @@ -23,6 +23,11 @@ export default class Queue { queueName: QueueName, jobId: string ): Promise { + + if(!jobId){ + return; + } + const job: Job | undefined = await this.getQueue(queueName).getJob( jobId ); diff --git a/CommonServer/Types/Workflow/Components/JSON/MergeJson.ts b/CommonServer/Types/Workflow/Components/JSON/MergeJson.ts index e35bdb8331..d765d22ecc 100644 --- a/CommonServer/Types/Workflow/Components/JSON/MergeJson.ts +++ b/CommonServer/Types/Workflow/Components/JSON/MergeJson.ts @@ -56,9 +56,9 @@ export default class MergeJSON extends ComponentCode { args['json1'] = JSON.parse(args['json1'] as string); } - if (typeof args['json2'] !== 'object') { + if (typeof args['json1'] !== 'object') { throw options.onError( - new BadDataException('JSON2 is should be of type object.') + new BadDataException('JSON1 is should be of type object.') ); } From 306a9975bceff0aa4c15beaf4e873a7f2665939d Mon Sep 17 00:00:00 2001 From: Simon Larsen Date: Wed, 1 Mar 2023 22:20:15 +0000 Subject: [PATCH 11/11] fix lint. --- CommonServer/Infrastructure/Queue.ts | 3 +- Workflow/Services/RunWorkflow.ts | 46 ++++++++++++++-------------- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/CommonServer/Infrastructure/Queue.ts b/CommonServer/Infrastructure/Queue.ts index 0f33a9ed2a..383a13db61 100644 --- a/CommonServer/Infrastructure/Queue.ts +++ b/CommonServer/Infrastructure/Queue.ts @@ -23,8 +23,7 @@ export default class Queue { queueName: QueueName, jobId: string ): Promise { - - if(!jobId){ + if (!jobId) { return; } diff --git a/Workflow/Services/RunWorkflow.ts b/Workflow/Services/RunWorkflow.ts index 116c0a9e2c..4f15ffabb9 100644 --- a/Workflow/Services/RunWorkflow.ts +++ b/Workflow/Services/RunWorkflow.ts @@ -158,8 +158,8 @@ export default class RunWorkflow { if (didWorkflowTimeOut) { throw new TimeoutException( 'Workflow execution time was more than ' + - runProps.timeout + - 'ms and workflow timed-out.' + runProps.timeout + + 'ms and workflow timed-out.' ); } @@ -171,8 +171,8 @@ export default class RunWorkflow { if (componentsExecuted.includes(executeComponentId)) { throw new BadDataException( 'Cyclic Workflow Detected. Cannot execute ' + - executeComponentId + - ' when it has already been executed.' + executeComponentId + + ' when it has already been executed.' ); } @@ -186,8 +186,8 @@ export default class RunWorkflow { if (!stackItem) { throw new BadDataException( 'Component with ID ' + - executeComponentId + - ' not found.' + executeComponentId + + ' not found.' ); } @@ -253,7 +253,7 @@ export default class RunWorkflow { this.log(result.returnValues); this.log( 'Executing Port: ' + result.executePort?.title || - '' + '' ); storageMap.local.components[stackItem.node.id] = { @@ -387,29 +387,29 @@ export default class RunWorkflow { argumentContent.toString().includes('{{') && argumentContent.toString().includes('}}') ) { + let argumentContentCopy: string = argumentContent.toString(); + const variablesInArgument: Array = []; + const regex: RegExp = /{{(.*?)}}/g; // Find all matches of the regular expression and capture the word between the braces {{x}} => x - - let argumentContentCopy = argumentContent.toString(); - const variablesInArgument = []; - - const regex = /{{(.*?)}}/g // Find all matches of the regular expression and capture the word between the braces {{x}} => x - - - let match; + let match: RegExpExecArray | null = null; while ((match = regex.exec(argumentContentCopy)) !== null) { - variablesInArgument.push(match[1]); + if (match[1]) { + variablesInArgument.push(match[1]); + } } - for(const variable of variablesInArgument){ - - const value = deepFind( + for (const variable of variablesInArgument) { + const value: string = deepFind( storageMap as any, variable as any ); - argumentContentCopy = argumentContentCopy.replace("{{"+variable+"}}", value); + argumentContentCopy = argumentContentCopy.replace( + '{{' + variable + '}}', + value + ); } argumentContent = argumentContentCopy; @@ -531,8 +531,8 @@ export default class RunWorkflow { } else { this.logs.push( OneUptimeDate.getCurrentDateAsFormattedString() + - ': ' + - JSON.stringify(data) + ': ' + + JSON.stringify(data) ); } } @@ -606,7 +606,7 @@ export default class RunWorkflow { const trigger: any | undefined = nodes.find((n: any) => { return ( (n.data as NodeDataProp).componentType === - ComponentType.Trigger && + ComponentType.Trigger && (n.data as NodeDataProp).nodeType === NodeType.Node ); });