@nocobase/plugin-workflow-request 1.0.0-alpha.2 → 1.0.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/RequestInstruction.d.ts +8 -0
- package/dist/client/index.d.ts +8 -0
- package/dist/client/index.js +9 -0
- package/dist/externalVersion.js +12 -3
- package/dist/index.d.ts +8 -0
- package/dist/index.js +9 -0
- package/dist/locale/index.d.ts +8 -0
- package/dist/locale/index.js +9 -0
- package/dist/server/Plugin.d.ts +8 -0
- package/dist/server/Plugin.js +9 -0
- package/dist/server/RequestInstruction.d.ts +8 -0
- package/dist/server/RequestInstruction.js +9 -0
- package/dist/server/index.d.ts +8 -0
- package/dist/server/index.js +9 -0
- package/package.json +2 -2
- package/src/client/RequestInstruction.tsx +0 -188
- package/src/client/index.ts +0 -18
- package/src/index.ts +0 -2
- package/src/locale/en-US.json +0 -20
- package/src/locale/es-ES.json +0 -19
- package/src/locale/fr-FR.json +0 -19
- package/src/locale/index.ts +0 -12
- package/src/locale/ko_KR.json +0 -22
- package/src/locale/pt-BR.json +0 -19
- package/src/locale/zh-CN.json +0 -20
- package/src/server/Plugin.ts +0 -11
- package/src/server/RequestInstruction.ts +0 -102
- package/src/server/__tests__/instruction.test.ts +0 -379
- package/src/server/index.ts +0 -1
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
1
9
|
import { Instruction, WorkflowVariableInput, WorkflowVariableJSON, WorkflowVariableTextArea } from '@nocobase/plugin-workflow/client';
|
|
2
10
|
export default class extends Instruction {
|
|
3
11
|
title: string;
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
1
9
|
import { Plugin } from '@nocobase/client';
|
|
2
10
|
export default class extends Plugin {
|
|
3
11
|
afterAdd(): Promise<void>;
|
package/dist/client/index.js
CHANGED
|
@@ -1 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
(function(t,o){typeof exports=="object"&&typeof module!="undefined"?o(exports,require("@nocobase/client"),require("@formily/antd-v5"),require("@nocobase/plugin-workflow/client"),require("react-i18next")):typeof define=="function"&&define.amd?define(["exports","@nocobase/client","@formily/antd-v5","@nocobase/plugin-workflow/client","react-i18next"],o):(t=typeof globalThis!="undefined"?globalThis:t||self,o(t["@nocobase/plugin-workflow-request"]={},t["@nocobase/client"],t["@formily/antd-v5"],t["@nocobase/plugin-workflow"]))})(this,function(t,o,r,a){"use strict";var x=Object.defineProperty;var y=(t,o,r)=>o in t?x(t,o,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[o]=r;var s=(t,o,r)=>(y(t,typeof o!="symbol"?o+"":o,r),r);var l=(t,o,r)=>new Promise((a,e)=>{var d=n=>{try{p(r.next(n))}catch(i){e(i)}},m=n=>{try{p(r.throw(n))}catch(i){e(i)}},p=n=>n.done?a(n.value):Promise.resolve(n.value).then(d,m);p((r=r.apply(t,o)).next())});const e="workflow-request";class d extends a.Instruction{constructor(){super(...arguments);s(this,"title",`{{t("HTTP request", { ns: "${e}" })}}`);s(this,"type","request");s(this,"group","extended");s(this,"description",`{{t("Send HTTP request to a URL. You can use the variables in the upstream nodes as request headers, parameters and request body.", { ns: "${e}" })}}`);s(this,"fieldset",{method:{type:"string",required:!0,title:`{{t("HTTP method", { ns: "${e}" })}}`,"x-decorator":"FormItem","x-component":"Select","x-component-props":{showSearch:!1,allowClear:!1,className:"auto-width"},enum:[{label:"GET",value:"GET"},{label:"POST",value:"POST"},{label:"PUT",value:"PUT"},{label:"PATCH",value:"PATCH"},{label:"DELETE",value:"DELETE"}],default:"POST"},url:{type:"string",required:!0,title:`{{t("URL", { ns: "${e}" })}}`,"x-decorator":"FormItem","x-decorator-props":{},"x-component":"WorkflowVariableTextArea","x-component-props":{placeholder:"https://www.nocobase.com"}},headers:{type:"array","x-component":"ArrayItems","x-decorator":"FormItem",title:`{{t("Headers", { ns: "${e}" })}}`,description:`{{t('"Content-Type" only support "application/json", and no need to specify', { ns: "${e}" })}}`,items:{type:"object",properties:{space:{type:"void","x-component":"Space",properties:{name:{type:"string","x-decorator":"FormItem","x-component":"Input","x-component-props":{placeholder:'{{t("Name")}}'}},value:{type:"string","x-decorator":"FormItem","x-component":"WorkflowVariableInput","x-component-props":{useTypedConstant:!0}},remove:{type:"void","x-decorator":"FormItem","x-component":"ArrayItems.Remove"}}}}},properties:{add:{type:"void",title:`{{t("Add request header", { ns: "${e}" })}}`,"x-component":"ArrayItems.Addition"}}},params:{type:"array","x-component":"ArrayItems","x-decorator":"FormItem",title:`{{t("Parameters", { ns: "${e}" })}}`,items:{type:"object",properties:{space:{type:"void","x-component":"Space",properties:{name:{type:"string","x-decorator":"FormItem","x-component":"Input","x-component-props":{placeholder:'{{t("Name")}}'}},value:{type:"string","x-decorator":"FormItem","x-component":"WorkflowVariableInput","x-component-props":{useTypedConstant:!0}},remove:{type:"void","x-decorator":"FormItem","x-component":"ArrayItems.Remove"}}}}},properties:{add:{type:"void",title:`{{t("Add parameter", { ns: "${e}" })}}`,"x-component":"ArrayItems.Addition"}}},data:{type:"string",title:`{{t("Body", { ns: "${e}" })}}`,"x-decorator":"FormItem","x-decorator-props":{},"x-component":"WorkflowVariableJSON","x-component-props":{changeOnSelect:!0,autoSize:{minRows:10},placeholder:`{{t("Input request data", { ns: "${e}" })}}`},description:`{{t("Only support standard JSON data", { ns: "${e}" })}}`},timeout:{type:"number",title:`{{t("Timeout config", { ns: "${e}" })}}`,"x-decorator":"FormItem","x-decorator-props":{},"x-component":"InputNumber","x-component-props":{addonAfter:`{{t("ms", { ns: "${e}" })}}`,min:1,step:1e3,defaultValue:5e3}},ignoreFail:{type:"boolean",title:`{{t("Ignore failed request and continue workflow", { ns: "${e}" })}}`,"x-decorator":"FormItem","x-component":"Checkbox"}});s(this,"components",{ArrayItems:r.ArrayItems,WorkflowVariableInput:a.WorkflowVariableInput,WorkflowVariableTextArea:a.WorkflowVariableTextArea,WorkflowVariableJSON:a.WorkflowVariableJSON})}useVariables({key:i,title:u},{types:f,fieldNames:c=a.defaultFieldNames}){return{[c.value]:i,[c.label]:u}}}class m extends o.Plugin{afterAdd(){return l(this,null,function*(){})}beforeLoad(){return l(this,null,function*(){})}load(){return l(this,null,function*(){this.app.pm.get("workflow").registerInstruction("request",d)})}}t.default=m,Object.defineProperties(t,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|
package/dist/externalVersion.js
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
module.exports = {
|
|
2
11
|
"@formily/antd-v5": "1.1.9",
|
|
3
|
-
"@nocobase/plugin-workflow": "1.0.0-alpha.
|
|
4
|
-
"@nocobase/client": "1.0.0-alpha.
|
|
12
|
+
"@nocobase/plugin-workflow": "1.0.0-alpha.3",
|
|
13
|
+
"@nocobase/client": "1.0.0-alpha.3",
|
|
5
14
|
"react-i18next": "11.18.6",
|
|
6
|
-
"@nocobase/server": "1.0.0-alpha.
|
|
15
|
+
"@nocobase/server": "1.0.0-alpha.3",
|
|
7
16
|
"axios": "0.26.1"
|
|
8
17
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
1
9
|
export * from './server';
|
|
2
10
|
export { default } from './server';
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
var __create = Object.create;
|
|
2
11
|
var __defProp = Object.defineProperty;
|
|
3
12
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
package/dist/locale/index.d.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
1
9
|
export declare const NAMESPACE = "workflow-request";
|
|
2
10
|
export declare function useLang(key: string, options?: {}): string;
|
|
3
11
|
export declare function usePluginTranslation(options: any): import("react-i18next").UseTranslationResponse<"workflow-request", undefined>;
|
package/dist/locale/index.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
var __defProp = Object.defineProperty;
|
|
2
11
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
12
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
package/dist/server/Plugin.d.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
1
9
|
import { Plugin } from '@nocobase/server';
|
|
2
10
|
export default class extends Plugin {
|
|
3
11
|
load(): Promise<void>;
|
package/dist/server/Plugin.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
var __create = Object.create;
|
|
2
11
|
var __defProp = Object.defineProperty;
|
|
3
12
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
1
9
|
import { AxiosRequestConfig } from 'axios';
|
|
2
10
|
import { Processor, Instruction, FlowNodeModel } from '@nocobase/plugin-workflow';
|
|
3
11
|
export interface Header {
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
var __create = Object.create;
|
|
2
11
|
var __defProp = Object.defineProperty;
|
|
3
12
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
1
9
|
export { default } from './Plugin';
|
package/dist/server/index.js
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
var __create = Object.create;
|
|
2
11
|
var __defProp = Object.defineProperty;
|
|
3
12
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"displayName.zh-CN": "工作流:HTTP 请求节点",
|
|
5
5
|
"description": "Send HTTP requests to any HTTP service for data interaction in workflow.",
|
|
6
6
|
"description.zh-CN": "可用于在工作流中向任意 HTTP 服务发送请求,进行数据交互。",
|
|
7
|
-
"version": "1.0.0-alpha.
|
|
7
|
+
"version": "1.0.0-alpha.3",
|
|
8
8
|
"license": "AGPL-3.0",
|
|
9
9
|
"main": "./dist/server/index.js",
|
|
10
10
|
"homepage": "https://docs.nocobase.com/handbook/workflow-request",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"@nocobase/server": "1.x",
|
|
25
25
|
"@nocobase/test": "1.x"
|
|
26
26
|
},
|
|
27
|
-
"gitHead": "
|
|
27
|
+
"gitHead": "7ccb137c7616cba5d238f87368239640e1d9ace1",
|
|
28
28
|
"keywords": [
|
|
29
29
|
"Workflow"
|
|
30
30
|
]
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
import { ArrayItems } from '@formily/antd-v5';
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
Instruction,
|
|
5
|
-
WorkflowVariableInput,
|
|
6
|
-
WorkflowVariableJSON,
|
|
7
|
-
WorkflowVariableTextArea,
|
|
8
|
-
defaultFieldNames,
|
|
9
|
-
} from '@nocobase/plugin-workflow/client';
|
|
10
|
-
|
|
11
|
-
import { NAMESPACE } from '../locale';
|
|
12
|
-
|
|
13
|
-
export default class extends Instruction {
|
|
14
|
-
title = `{{t("HTTP request", { ns: "${NAMESPACE}" })}}`;
|
|
15
|
-
type = 'request';
|
|
16
|
-
group = 'extended';
|
|
17
|
-
description = `{{t("Send HTTP request to a URL. You can use the variables in the upstream nodes as request headers, parameters and request body.", { ns: "${NAMESPACE}" })}}`;
|
|
18
|
-
fieldset = {
|
|
19
|
-
method: {
|
|
20
|
-
type: 'string',
|
|
21
|
-
required: true,
|
|
22
|
-
title: `{{t("HTTP method", { ns: "${NAMESPACE}" })}}`,
|
|
23
|
-
'x-decorator': 'FormItem',
|
|
24
|
-
'x-component': 'Select',
|
|
25
|
-
'x-component-props': {
|
|
26
|
-
showSearch: false,
|
|
27
|
-
allowClear: false,
|
|
28
|
-
className: 'auto-width',
|
|
29
|
-
},
|
|
30
|
-
enum: [
|
|
31
|
-
{ label: 'GET', value: 'GET' },
|
|
32
|
-
{ label: 'POST', value: 'POST' },
|
|
33
|
-
{ label: 'PUT', value: 'PUT' },
|
|
34
|
-
{ label: 'PATCH', value: 'PATCH' },
|
|
35
|
-
{ label: 'DELETE', value: 'DELETE' },
|
|
36
|
-
],
|
|
37
|
-
default: 'POST',
|
|
38
|
-
},
|
|
39
|
-
url: {
|
|
40
|
-
type: 'string',
|
|
41
|
-
required: true,
|
|
42
|
-
title: `{{t("URL", { ns: "${NAMESPACE}" })}}`,
|
|
43
|
-
'x-decorator': 'FormItem',
|
|
44
|
-
'x-decorator-props': {},
|
|
45
|
-
'x-component': 'WorkflowVariableTextArea',
|
|
46
|
-
'x-component-props': {
|
|
47
|
-
placeholder: 'https://www.nocobase.com',
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
headers: {
|
|
51
|
-
type: 'array',
|
|
52
|
-
'x-component': 'ArrayItems',
|
|
53
|
-
'x-decorator': 'FormItem',
|
|
54
|
-
title: `{{t("Headers", { ns: "${NAMESPACE}" })}}`,
|
|
55
|
-
description: `{{t('"Content-Type" only support "application/json", and no need to specify', { ns: "${NAMESPACE}" })}}`,
|
|
56
|
-
items: {
|
|
57
|
-
type: 'object',
|
|
58
|
-
properties: {
|
|
59
|
-
space: {
|
|
60
|
-
type: 'void',
|
|
61
|
-
'x-component': 'Space',
|
|
62
|
-
properties: {
|
|
63
|
-
name: {
|
|
64
|
-
type: 'string',
|
|
65
|
-
'x-decorator': 'FormItem',
|
|
66
|
-
'x-component': 'Input',
|
|
67
|
-
'x-component-props': {
|
|
68
|
-
placeholder: `{{t("Name")}}`,
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
value: {
|
|
72
|
-
type: 'string',
|
|
73
|
-
'x-decorator': 'FormItem',
|
|
74
|
-
'x-component': 'WorkflowVariableInput',
|
|
75
|
-
'x-component-props': {
|
|
76
|
-
useTypedConstant: true,
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
remove: {
|
|
80
|
-
type: 'void',
|
|
81
|
-
'x-decorator': 'FormItem',
|
|
82
|
-
'x-component': 'ArrayItems.Remove',
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
},
|
|
88
|
-
properties: {
|
|
89
|
-
add: {
|
|
90
|
-
type: 'void',
|
|
91
|
-
title: `{{t("Add request header", { ns: "${NAMESPACE}" })}}`,
|
|
92
|
-
'x-component': 'ArrayItems.Addition',
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
params: {
|
|
97
|
-
type: 'array',
|
|
98
|
-
'x-component': 'ArrayItems',
|
|
99
|
-
'x-decorator': 'FormItem',
|
|
100
|
-
title: `{{t("Parameters", { ns: "${NAMESPACE}" })}}`,
|
|
101
|
-
items: {
|
|
102
|
-
type: 'object',
|
|
103
|
-
properties: {
|
|
104
|
-
space: {
|
|
105
|
-
type: 'void',
|
|
106
|
-
'x-component': 'Space',
|
|
107
|
-
properties: {
|
|
108
|
-
name: {
|
|
109
|
-
type: 'string',
|
|
110
|
-
'x-decorator': 'FormItem',
|
|
111
|
-
'x-component': 'Input',
|
|
112
|
-
'x-component-props': {
|
|
113
|
-
placeholder: `{{t("Name")}}`,
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
value: {
|
|
117
|
-
type: 'string',
|
|
118
|
-
'x-decorator': 'FormItem',
|
|
119
|
-
'x-component': 'WorkflowVariableInput',
|
|
120
|
-
'x-component-props': {
|
|
121
|
-
useTypedConstant: true,
|
|
122
|
-
},
|
|
123
|
-
},
|
|
124
|
-
remove: {
|
|
125
|
-
type: 'void',
|
|
126
|
-
'x-decorator': 'FormItem',
|
|
127
|
-
'x-component': 'ArrayItems.Remove',
|
|
128
|
-
},
|
|
129
|
-
},
|
|
130
|
-
},
|
|
131
|
-
},
|
|
132
|
-
},
|
|
133
|
-
properties: {
|
|
134
|
-
add: {
|
|
135
|
-
type: 'void',
|
|
136
|
-
title: `{{t("Add parameter", { ns: "${NAMESPACE}" })}}`,
|
|
137
|
-
'x-component': 'ArrayItems.Addition',
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
},
|
|
141
|
-
data: {
|
|
142
|
-
type: 'string',
|
|
143
|
-
title: `{{t("Body", { ns: "${NAMESPACE}" })}}`,
|
|
144
|
-
'x-decorator': 'FormItem',
|
|
145
|
-
'x-decorator-props': {},
|
|
146
|
-
'x-component': 'WorkflowVariableJSON',
|
|
147
|
-
'x-component-props': {
|
|
148
|
-
changeOnSelect: true,
|
|
149
|
-
autoSize: {
|
|
150
|
-
minRows: 10,
|
|
151
|
-
},
|
|
152
|
-
placeholder: `{{t("Input request data", { ns: "${NAMESPACE}" })}}`,
|
|
153
|
-
},
|
|
154
|
-
description: `{{t("Only support standard JSON data", { ns: "${NAMESPACE}" })}}`,
|
|
155
|
-
},
|
|
156
|
-
timeout: {
|
|
157
|
-
type: 'number',
|
|
158
|
-
title: `{{t("Timeout config", { ns: "${NAMESPACE}" })}}`,
|
|
159
|
-
'x-decorator': 'FormItem',
|
|
160
|
-
'x-decorator-props': {},
|
|
161
|
-
'x-component': 'InputNumber',
|
|
162
|
-
'x-component-props': {
|
|
163
|
-
addonAfter: `{{t("ms", { ns: "${NAMESPACE}" })}}`,
|
|
164
|
-
min: 1,
|
|
165
|
-
step: 1000,
|
|
166
|
-
defaultValue: 5000,
|
|
167
|
-
},
|
|
168
|
-
},
|
|
169
|
-
ignoreFail: {
|
|
170
|
-
type: 'boolean',
|
|
171
|
-
title: `{{t("Ignore failed request and continue workflow", { ns: "${NAMESPACE}" })}}`,
|
|
172
|
-
'x-decorator': 'FormItem',
|
|
173
|
-
'x-component': 'Checkbox',
|
|
174
|
-
},
|
|
175
|
-
};
|
|
176
|
-
components = {
|
|
177
|
-
ArrayItems,
|
|
178
|
-
WorkflowVariableInput,
|
|
179
|
-
WorkflowVariableTextArea,
|
|
180
|
-
WorkflowVariableJSON,
|
|
181
|
-
};
|
|
182
|
-
useVariables({ key, title }, { types, fieldNames = defaultFieldNames }) {
|
|
183
|
-
return {
|
|
184
|
-
[fieldNames.value]: key,
|
|
185
|
-
[fieldNames.label]: title,
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
}
|
package/src/client/index.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { Plugin } from '@nocobase/client';
|
|
2
|
-
import WorkflowPlugin from '@nocobase/plugin-workflow/client';
|
|
3
|
-
|
|
4
|
-
import RequestInstruction from './RequestInstruction';
|
|
5
|
-
|
|
6
|
-
export default class extends Plugin {
|
|
7
|
-
async afterAdd() {
|
|
8
|
-
// await this.app.pm.add()
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
async beforeLoad() {}
|
|
12
|
-
|
|
13
|
-
// You can get and modify the app instance here
|
|
14
|
-
async load() {
|
|
15
|
-
const workflow = this.app.pm.get('workflow') as WorkflowPlugin;
|
|
16
|
-
workflow.registerInstruction('request', RequestInstruction);
|
|
17
|
-
}
|
|
18
|
-
}
|
package/src/index.ts
DELETED
package/src/locale/en-US.json
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"HTTP request": "HTTP request",
|
|
3
|
-
"Send HTTP request to a URL. You can use the variables in the upstream nodes as request headers, parameters and request body.": "Send HTTP request to a URL. You can use the variables in the upstream nodes as request headers, parameters and request body.",
|
|
4
|
-
"HTTP method": "HTTP method",
|
|
5
|
-
"URL": "URL",
|
|
6
|
-
"Headers": "Headers",
|
|
7
|
-
"Add request header": "Add request header",
|
|
8
|
-
"Parameters": "Parameters",
|
|
9
|
-
"Add parameter": "Add parameter",
|
|
10
|
-
"Body": "Body",
|
|
11
|
-
"Use variable": "Use variable",
|
|
12
|
-
"Format": "Format",
|
|
13
|
-
"Insert": "Insert",
|
|
14
|
-
"Timeout config": "Timeout config",
|
|
15
|
-
"ms": "ms",
|
|
16
|
-
"Input request data": "Input request data",
|
|
17
|
-
"Only support standard JSON data": "Only support standard JSON data",
|
|
18
|
-
"\"Content-Type\" only support \"application/json\", and no need to specify": "\"Content-Type\" only support \"application/json\", and no need to specify",
|
|
19
|
-
"Ignore failed request and continue workflow": "Ignore failed request and continue workflow"
|
|
20
|
-
}
|
package/src/locale/es-ES.json
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"HTTP request": "Petición HTTP",
|
|
3
|
-
"HTTP method": "Método HTTP",
|
|
4
|
-
"URL": "URL",
|
|
5
|
-
"Headers": "Encabezados",
|
|
6
|
-
"Add request header": "Añadir encabezado de petición",
|
|
7
|
-
"Parameters": "Parámetros",
|
|
8
|
-
"Add parameter": "Añadir parámetro",
|
|
9
|
-
"Body": "Cuerpo",
|
|
10
|
-
"Use variable": "Utilizar variable",
|
|
11
|
-
"Format": "Formato",
|
|
12
|
-
"Insert": "Insertar",
|
|
13
|
-
"Timeout config": "Tiempo de espera config",
|
|
14
|
-
"ms": "ms",
|
|
15
|
-
"Input request data": "Datos de solicitud de entrada",
|
|
16
|
-
"Only support standard JSON data": "Sólo admite datos JSON estándar",
|
|
17
|
-
"\"Content-Type\" only support \"application/json\", and no need to specify": "\"Content-Type\" sólo admite \"application/json\", y no es necesario especificar",
|
|
18
|
-
"Ignore fail request and continue workflow": "Ignorar solicitud fallida y continuar flujo de trabajo"
|
|
19
|
-
}
|
package/src/locale/fr-FR.json
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"HTTP request": "Requête HTTP",
|
|
3
|
-
"HTTP method": "Méthode HTTP",
|
|
4
|
-
"URL": "URL",
|
|
5
|
-
"Headers": "En-têtes",
|
|
6
|
-
"Add request header": "Ajouter un en-tête de requête",
|
|
7
|
-
"Parameters": "Paramètres",
|
|
8
|
-
"Add parameter": "Ajouter un paramètre",
|
|
9
|
-
"Body": "Corps",
|
|
10
|
-
"Use variable": "Utiliser une variable",
|
|
11
|
-
"Format": "Format",
|
|
12
|
-
"Insert": "Insérer",
|
|
13
|
-
"Timeout config": "Configuration du délai d'expiration",
|
|
14
|
-
"ms": "ms",
|
|
15
|
-
"Input request data": "Entrée des données de requête",
|
|
16
|
-
"Only support standard JSON data": "Prend uniquement en charge les données JSON standard",
|
|
17
|
-
"\"Content-Type\" only support \"application/json\", and no need to specify": "\"Content-Type\" prend uniquement en charge \"application/json\" et n'a pas besoin d'être spécifié",
|
|
18
|
-
"Ignore fail request and continue workflow": "Ignorer l'échec de la requête et continuer le workflow"
|
|
19
|
-
}
|
package/src/locale/index.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { useTranslation } from 'react-i18next';
|
|
2
|
-
|
|
3
|
-
export const NAMESPACE = 'workflow-request';
|
|
4
|
-
|
|
5
|
-
export function useLang(key: string, options = {}) {
|
|
6
|
-
const { t } = usePluginTranslation(options);
|
|
7
|
-
return t(key);
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function usePluginTranslation(options) {
|
|
11
|
-
return useTranslation(NAMESPACE, options);
|
|
12
|
-
}
|
package/src/locale/ko_KR.json
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"HTTP request": "HTTP 요청",
|
|
3
|
-
"Send HTTP request to a URL. You can use the variables in the upstream nodes as request headers, parameters and request body.":
|
|
4
|
-
"URL에 HTTP 요청을 보냅니다. 상류 노드의 변수를 요청 헤더, 매개변수 및 요청 본문으로 사용할 수 있습니다.",
|
|
5
|
-
"HTTP method": "HTTP 메서드",
|
|
6
|
-
"URL": "주소",
|
|
7
|
-
"Headers": "헤더",
|
|
8
|
-
"Add request header": "요청 헤더 추가",
|
|
9
|
-
"Parameters": "매개변수",
|
|
10
|
-
"Add parameter": "매개변수 추가",
|
|
11
|
-
"Body": "본문",
|
|
12
|
-
"Use variable": "변수 사용",
|
|
13
|
-
"Format": "형식",
|
|
14
|
-
"Insert": "삽입",
|
|
15
|
-
"Timeout config": "시간 초과 설정",
|
|
16
|
-
"ms": "밀리초",
|
|
17
|
-
"Input request data": "요청 데이터 입력",
|
|
18
|
-
"Only support standard JSON data": "표준 JSON 데이터만 지원합니다",
|
|
19
|
-
"\"Content-Type\" only support \"application/json\", and no need to specify":
|
|
20
|
-
"\"Content-Type\" 헤더는 \"application/json\"만 지원하며 지정할 필요가 없습니다",
|
|
21
|
-
"Ignore failed request and continue workflow": "실패한 요청을 무시하고 워크플로를 계속합니다"
|
|
22
|
-
}
|
package/src/locale/pt-BR.json
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"HTTP request": "Requisição HTTP",
|
|
3
|
-
"HTTP method": "Método HTTP",
|
|
4
|
-
"URL": "URL",
|
|
5
|
-
"Headers": "Cabeçalhos",
|
|
6
|
-
"Add request header": "Adicionar cabeçalho de requisição",
|
|
7
|
-
"Parameters": "Parâmetros",
|
|
8
|
-
"Add parameter": "Adicionar parâmetro",
|
|
9
|
-
"Body": "Corpo",
|
|
10
|
-
"Use variable": "Usar variável",
|
|
11
|
-
"Format": "Formato",
|
|
12
|
-
"Insert": "Inserir",
|
|
13
|
-
"Timeout config": "Configuração de tempo limite",
|
|
14
|
-
"ms": "ms",
|
|
15
|
-
"Input request data": "Dados de entrada da requisição",
|
|
16
|
-
"Only support standard JSON data": "Suporta somente dados JSON padrão",
|
|
17
|
-
"\"Content-Type\" only support \"application/json\", and no need to specify": "\"Content-Type\" somente suporta \"application/json\" e não precisa ser especificado",
|
|
18
|
-
"Ignore fail request and continue workflow": "Ignorar falhas na requisição e continuar o fluxo de trabalho"
|
|
19
|
-
}
|
package/src/locale/zh-CN.json
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"HTTP request": "HTTP 请求",
|
|
3
|
-
"Send HTTP request to a URL. You can use the variables in the upstream nodes as request headers, parameters and request body.": "向指定 URL 发送 HTTP 请求。可以使用上游节点里的变量作为请求头、参数和请求体。",
|
|
4
|
-
"HTTP method": "HTTP 方法",
|
|
5
|
-
"URL": "地址",
|
|
6
|
-
"Headers": "请求头",
|
|
7
|
-
"Add request header": "添加请求头",
|
|
8
|
-
"Parameters": "参数",
|
|
9
|
-
"Add parameter": "添加参数",
|
|
10
|
-
"Body": "请求体",
|
|
11
|
-
"Use variable": "使用变量",
|
|
12
|
-
"Format": "格式化",
|
|
13
|
-
"Insert": "插入",
|
|
14
|
-
"Timeout config": "超时设置",
|
|
15
|
-
"ms": "毫秒",
|
|
16
|
-
"Input request data": "输入请求数据",
|
|
17
|
-
"Only support standard JSON data": "仅支持标准 JSON 数据",
|
|
18
|
-
"\"Content-Type\" only support \"application/json\", and no need to specify": "\"Content-Type\" 请求头仅支持 \"application/json\",无需填写",
|
|
19
|
-
"Ignore failed request and continue workflow": "忽略失败的请求并继续工作流"
|
|
20
|
-
}
|
package/src/server/Plugin.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Plugin } from '@nocobase/server';
|
|
2
|
-
import WorkflowPlugin from '@nocobase/plugin-workflow';
|
|
3
|
-
|
|
4
|
-
import RequestInstruction from './RequestInstruction';
|
|
5
|
-
|
|
6
|
-
export default class extends Plugin {
|
|
7
|
-
async load() {
|
|
8
|
-
const workflowPlugin = this.app.getPlugin<WorkflowPlugin>(WorkflowPlugin);
|
|
9
|
-
workflowPlugin.registerInstruction('request', RequestInstruction);
|
|
10
|
-
}
|
|
11
|
-
}
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import axios, { AxiosRequestConfig } from 'axios';
|
|
2
|
-
|
|
3
|
-
import { Processor, Instruction, JOB_STATUS, FlowNodeModel } from '@nocobase/plugin-workflow';
|
|
4
|
-
|
|
5
|
-
export interface Header {
|
|
6
|
-
name: string;
|
|
7
|
-
value: string;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export type RequestConfig = Pick<AxiosRequestConfig, 'url' | 'method' | 'params' | 'data' | 'timeout'> & {
|
|
11
|
-
headers: Array<Header>;
|
|
12
|
-
ignoreFail: boolean;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
async function request(config) {
|
|
16
|
-
// default headers
|
|
17
|
-
const { url, method = 'POST', data, timeout = 5000 } = config;
|
|
18
|
-
const headers = (config.headers ?? []).reduce((result, header) => {
|
|
19
|
-
if (header.name.toLowerCase() === 'content-type') {
|
|
20
|
-
return result;
|
|
21
|
-
}
|
|
22
|
-
return Object.assign(result, { [header.name]: header.value });
|
|
23
|
-
}, {});
|
|
24
|
-
const params = (config.params ?? []).reduce(
|
|
25
|
-
(result, param) => Object.assign(result, { [param.name]: param.value }),
|
|
26
|
-
{},
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
// TODO(feat): only support JSON type for now, should support others in future
|
|
30
|
-
headers['Content-Type'] = 'application/json';
|
|
31
|
-
|
|
32
|
-
return axios.request({
|
|
33
|
-
url,
|
|
34
|
-
method,
|
|
35
|
-
headers,
|
|
36
|
-
params,
|
|
37
|
-
data,
|
|
38
|
-
timeout,
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export default class extends Instruction {
|
|
43
|
-
async run(node: FlowNodeModel, prevJob, processor: Processor) {
|
|
44
|
-
const config = processor.getParsedValue(node.config, node.id) as RequestConfig;
|
|
45
|
-
|
|
46
|
-
const { workflow } = processor.execution;
|
|
47
|
-
const sync = this.workflow.isWorkflowSync(workflow);
|
|
48
|
-
|
|
49
|
-
if (sync) {
|
|
50
|
-
try {
|
|
51
|
-
const response = await request(config);
|
|
52
|
-
return {
|
|
53
|
-
status: JOB_STATUS.RESOLVED,
|
|
54
|
-
result: response.data,
|
|
55
|
-
};
|
|
56
|
-
} catch (error) {
|
|
57
|
-
return {
|
|
58
|
-
status: JOB_STATUS.FAILED,
|
|
59
|
-
result: error.isAxiosError ? error.toJSON() : error.message,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const job = await processor.saveJob({
|
|
65
|
-
status: JOB_STATUS.PENDING,
|
|
66
|
-
nodeId: node.id,
|
|
67
|
-
nodeKey: node.key,
|
|
68
|
-
upstreamId: prevJob?.id ?? null,
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
// eslint-disable-next-line promise/catch-or-return
|
|
72
|
-
request(config)
|
|
73
|
-
.then((response) => {
|
|
74
|
-
job.set({
|
|
75
|
-
status: JOB_STATUS.RESOLVED,
|
|
76
|
-
result: response.data,
|
|
77
|
-
});
|
|
78
|
-
})
|
|
79
|
-
.catch((error) => {
|
|
80
|
-
job.set({
|
|
81
|
-
status: JOB_STATUS.FAILED,
|
|
82
|
-
result: error.isAxiosError ? error.toJSON() : error.message,
|
|
83
|
-
});
|
|
84
|
-
})
|
|
85
|
-
.finally(() => {
|
|
86
|
-
processor.logger.info(`request (#${node.id}) response received, status: ${job.get('status')}`);
|
|
87
|
-
this.workflow.resume(job);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
processor.logger.info(`request (#${node.id}) sent to "${config.url}", waiting for response...`);
|
|
91
|
-
|
|
92
|
-
return processor.exit();
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
async resume(node: FlowNodeModel, job, processor: Processor) {
|
|
96
|
-
const { ignoreFail } = node.config as RequestConfig;
|
|
97
|
-
if (ignoreFail) {
|
|
98
|
-
job.set('status', JOB_STATUS.RESOLVED);
|
|
99
|
-
}
|
|
100
|
-
return job;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
@@ -1,379 +0,0 @@
|
|
|
1
|
-
import { Server } from 'http';
|
|
2
|
-
import jwt from 'jsonwebtoken';
|
|
3
|
-
import Koa from 'koa';
|
|
4
|
-
import bodyParser from 'koa-bodyparser';
|
|
5
|
-
|
|
6
|
-
import Database from '@nocobase/database';
|
|
7
|
-
import { MockServer } from '@nocobase/test';
|
|
8
|
-
|
|
9
|
-
import PluginWorkflow, { Processor, EXECUTION_STATUS, JOB_STATUS } from '@nocobase/plugin-workflow';
|
|
10
|
-
import { getApp, sleep } from '@nocobase/plugin-workflow-test';
|
|
11
|
-
|
|
12
|
-
import { RequestConfig } from '../RequestInstruction';
|
|
13
|
-
|
|
14
|
-
const HOST = 'localhost';
|
|
15
|
-
|
|
16
|
-
function getRandomPort() {
|
|
17
|
-
const minPort = 1024;
|
|
18
|
-
const maxPort = 49151;
|
|
19
|
-
return Math.floor(Math.random() * (maxPort - minPort + 1)) + minPort;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
class MockAPI {
|
|
23
|
-
app: Koa;
|
|
24
|
-
server: Server;
|
|
25
|
-
port: number;
|
|
26
|
-
get URL_DATA() {
|
|
27
|
-
return `http://${HOST}:${this.port}/api/data`;
|
|
28
|
-
}
|
|
29
|
-
get URL_400() {
|
|
30
|
-
return `http://${HOST}:${this.port}/api/400`;
|
|
31
|
-
}
|
|
32
|
-
get URL_TIMEOUT() {
|
|
33
|
-
return `http://${HOST}:${this.port}/api/timeout`;
|
|
34
|
-
}
|
|
35
|
-
constructor() {
|
|
36
|
-
this.app = new Koa();
|
|
37
|
-
this.app.use(bodyParser());
|
|
38
|
-
|
|
39
|
-
this.app.use(async (ctx, next) => {
|
|
40
|
-
if (ctx.path === '/api/400') {
|
|
41
|
-
return ctx.throw(400);
|
|
42
|
-
}
|
|
43
|
-
if (ctx.path === '/api/timeout') {
|
|
44
|
-
await sleep(2000);
|
|
45
|
-
ctx.status = 204;
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
if (ctx.path === '/api/data') {
|
|
49
|
-
await sleep(100);
|
|
50
|
-
ctx.body = {
|
|
51
|
-
meta: { title: ctx.query.title },
|
|
52
|
-
data: { title: ctx.request.body['title'] },
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
await next();
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
async start() {
|
|
60
|
-
return new Promise((resolve) => {
|
|
61
|
-
this.server = this.app.listen(0, () => {
|
|
62
|
-
this.port = this.server.address()['port'];
|
|
63
|
-
resolve(true);
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
async close() {
|
|
69
|
-
return new Promise((resolve) => {
|
|
70
|
-
this.server.close(() => {
|
|
71
|
-
resolve(true);
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
describe('workflow > instructions > request', () => {
|
|
78
|
-
let app: MockServer;
|
|
79
|
-
let db: Database;
|
|
80
|
-
let PostRepo;
|
|
81
|
-
let PostCollection;
|
|
82
|
-
let ReplyRepo;
|
|
83
|
-
let WorkflowModel;
|
|
84
|
-
let workflow;
|
|
85
|
-
let api: MockAPI;
|
|
86
|
-
|
|
87
|
-
beforeEach(async () => {
|
|
88
|
-
api = new MockAPI();
|
|
89
|
-
api.start();
|
|
90
|
-
app = await getApp({
|
|
91
|
-
resourcer: {
|
|
92
|
-
prefix: '/api',
|
|
93
|
-
},
|
|
94
|
-
plugins: ['users', 'auth', 'workflow-request'],
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
db = app.db;
|
|
98
|
-
WorkflowModel = db.getCollection('workflows').model;
|
|
99
|
-
PostCollection = db.getCollection('posts');
|
|
100
|
-
PostRepo = PostCollection.repository;
|
|
101
|
-
ReplyRepo = db.getCollection('replies').repository;
|
|
102
|
-
|
|
103
|
-
workflow = await WorkflowModel.create({
|
|
104
|
-
enabled: true,
|
|
105
|
-
type: 'collection',
|
|
106
|
-
config: {
|
|
107
|
-
mode: 1,
|
|
108
|
-
collection: 'posts',
|
|
109
|
-
},
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
afterEach(async () => {
|
|
114
|
-
await api.close();
|
|
115
|
-
await app.destroy();
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
describe('request static app routes', () => {
|
|
119
|
-
it('get data', async () => {
|
|
120
|
-
await workflow.createNode({
|
|
121
|
-
type: 'request',
|
|
122
|
-
config: {
|
|
123
|
-
url: api.URL_DATA,
|
|
124
|
-
method: 'GET',
|
|
125
|
-
} as RequestConfig,
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
await PostRepo.create({ values: { title: 't1' } });
|
|
129
|
-
|
|
130
|
-
await sleep(500);
|
|
131
|
-
|
|
132
|
-
const [execution] = await workflow.getExecutions();
|
|
133
|
-
expect(execution.status).toEqual(EXECUTION_STATUS.RESOLVED);
|
|
134
|
-
const [job] = await execution.getJobs();
|
|
135
|
-
expect(job.status).toEqual(JOB_STATUS.RESOLVED);
|
|
136
|
-
expect(job.result).toEqual({ meta: {}, data: {} });
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
it('timeout', async () => {
|
|
140
|
-
await workflow.createNode({
|
|
141
|
-
type: 'request',
|
|
142
|
-
config: {
|
|
143
|
-
url: api.URL_TIMEOUT,
|
|
144
|
-
method: 'GET',
|
|
145
|
-
timeout: 250,
|
|
146
|
-
} as RequestConfig,
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
await PostRepo.create({ values: { title: 't1' } });
|
|
150
|
-
|
|
151
|
-
await sleep(1000);
|
|
152
|
-
|
|
153
|
-
const [execution] = await workflow.getExecutions();
|
|
154
|
-
const [job] = await execution.getJobs();
|
|
155
|
-
expect(job.status).toEqual(JOB_STATUS.FAILED);
|
|
156
|
-
|
|
157
|
-
expect(job.result).toMatchObject({
|
|
158
|
-
code: 'ECONNABORTED',
|
|
159
|
-
name: 'Error',
|
|
160
|
-
status: null,
|
|
161
|
-
message: 'timeout of 250ms exceeded',
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
// NOTE: to wait for the response to finish and avoid non finished promise.
|
|
165
|
-
await sleep(1500);
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
it('ignoreFail', async () => {
|
|
169
|
-
await workflow.createNode({
|
|
170
|
-
type: 'request',
|
|
171
|
-
config: {
|
|
172
|
-
url: api.URL_TIMEOUT,
|
|
173
|
-
method: 'GET',
|
|
174
|
-
timeout: 250,
|
|
175
|
-
ignoreFail: true,
|
|
176
|
-
} as RequestConfig,
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
await PostRepo.create({ values: { title: 't1' } });
|
|
180
|
-
|
|
181
|
-
await sleep(1000);
|
|
182
|
-
|
|
183
|
-
const [execution] = await workflow.getExecutions();
|
|
184
|
-
const [job] = await execution.getJobs();
|
|
185
|
-
expect(job.status).toEqual(JOB_STATUS.RESOLVED);
|
|
186
|
-
expect(job.result).toMatchObject({
|
|
187
|
-
code: 'ECONNABORTED',
|
|
188
|
-
name: 'Error',
|
|
189
|
-
status: null,
|
|
190
|
-
message: 'timeout of 250ms exceeded',
|
|
191
|
-
});
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
it('response 400', async () => {
|
|
195
|
-
await workflow.createNode({
|
|
196
|
-
type: 'request',
|
|
197
|
-
config: {
|
|
198
|
-
url: api.URL_400,
|
|
199
|
-
method: 'GET',
|
|
200
|
-
ignoreFail: false,
|
|
201
|
-
} as RequestConfig,
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
await PostRepo.create({ values: { title: 't1' } });
|
|
205
|
-
|
|
206
|
-
await sleep(500);
|
|
207
|
-
|
|
208
|
-
const [execution] = await workflow.getExecutions();
|
|
209
|
-
const [job] = await execution.getJobs();
|
|
210
|
-
expect(job.status).toEqual(JOB_STATUS.FAILED);
|
|
211
|
-
expect(job.result.status).toBe(400);
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
it('response 400 ignoreFail', async () => {
|
|
215
|
-
await workflow.createNode({
|
|
216
|
-
type: 'request',
|
|
217
|
-
config: {
|
|
218
|
-
url: api.URL_400,
|
|
219
|
-
method: 'GET',
|
|
220
|
-
timeout: 1000,
|
|
221
|
-
ignoreFail: true,
|
|
222
|
-
} as RequestConfig,
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
await PostRepo.create({ values: { title: 't1' } });
|
|
226
|
-
|
|
227
|
-
await sleep(500);
|
|
228
|
-
|
|
229
|
-
const [execution] = await workflow.getExecutions();
|
|
230
|
-
const [job] = await execution.getJobs();
|
|
231
|
-
expect(job.status).toEqual(JOB_STATUS.RESOLVED);
|
|
232
|
-
expect(job.result.status).toBe(400);
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
it('request with data', async () => {
|
|
236
|
-
const n1 = await workflow.createNode({
|
|
237
|
-
type: 'request',
|
|
238
|
-
config: {
|
|
239
|
-
url: api.URL_DATA,
|
|
240
|
-
method: 'POST',
|
|
241
|
-
data: { title: '{{$context.data.title}}' },
|
|
242
|
-
} as RequestConfig,
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
await PostRepo.create({ values: { title: 't1' } });
|
|
246
|
-
|
|
247
|
-
await sleep(500);
|
|
248
|
-
|
|
249
|
-
const [execution] = await workflow.getExecutions();
|
|
250
|
-
const [job] = await execution.getJobs();
|
|
251
|
-
expect(job.status).toEqual(JOB_STATUS.RESOLVED);
|
|
252
|
-
expect(job.result.data).toEqual({ title: 't1' });
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
// TODO(bug): should not use ejs
|
|
256
|
-
it('request json data with multiple lines', async () => {
|
|
257
|
-
const n1 = await workflow.createNode({
|
|
258
|
-
type: 'request',
|
|
259
|
-
config: {
|
|
260
|
-
url: api.URL_DATA,
|
|
261
|
-
method: 'POST',
|
|
262
|
-
data: { title: '{{$context.data.title}}' },
|
|
263
|
-
} as RequestConfig,
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
const title = 't1\n\nline 2';
|
|
267
|
-
await PostRepo.create({
|
|
268
|
-
values: { title },
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
await sleep(500);
|
|
272
|
-
|
|
273
|
-
const [execution] = await workflow.getExecutions();
|
|
274
|
-
const [job] = await execution.getJobs();
|
|
275
|
-
expect(job.status).toEqual(JOB_STATUS.RESOLVED);
|
|
276
|
-
expect(job.result.data).toEqual({ title });
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
it.skip('request inside loop', async () => {
|
|
280
|
-
const n1 = await workflow.createNode({
|
|
281
|
-
type: 'loop',
|
|
282
|
-
config: {
|
|
283
|
-
target: 2,
|
|
284
|
-
},
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
const n2 = await workflow.createNode({
|
|
288
|
-
type: 'request',
|
|
289
|
-
upstreamId: n1.id,
|
|
290
|
-
branchIndex: 0,
|
|
291
|
-
config: {
|
|
292
|
-
url: api.URL_DATA,
|
|
293
|
-
method: 'GET',
|
|
294
|
-
},
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
await PostRepo.create({ values: { title: 't1' } });
|
|
298
|
-
|
|
299
|
-
await sleep(500);
|
|
300
|
-
|
|
301
|
-
const [execution] = await workflow.getExecutions();
|
|
302
|
-
expect(execution.status).toEqual(EXECUTION_STATUS.RESOLVED);
|
|
303
|
-
const jobs = await execution.getJobs({ order: [['id', 'ASC']] });
|
|
304
|
-
expect(jobs.length).toBe(3);
|
|
305
|
-
expect(jobs.map((item) => item.status)).toEqual(Array(3).fill(JOB_STATUS.RESOLVED));
|
|
306
|
-
expect(jobs[0].result).toBe(2);
|
|
307
|
-
});
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
describe('request db resource', () => {
|
|
311
|
-
it('request db resource', async () => {
|
|
312
|
-
const user = await db.getRepository('users').create({});
|
|
313
|
-
|
|
314
|
-
const token = jwt.sign(
|
|
315
|
-
{
|
|
316
|
-
userId: typeof user.id,
|
|
317
|
-
},
|
|
318
|
-
process.env.APP_KEY,
|
|
319
|
-
{
|
|
320
|
-
expiresIn: '1d',
|
|
321
|
-
},
|
|
322
|
-
);
|
|
323
|
-
|
|
324
|
-
const server = app.listen(12346, () => {});
|
|
325
|
-
|
|
326
|
-
await sleep(1000);
|
|
327
|
-
|
|
328
|
-
const n1 = await workflow.createNode({
|
|
329
|
-
type: 'request',
|
|
330
|
-
config: {
|
|
331
|
-
url: `http://localhost:12346/api/categories`,
|
|
332
|
-
method: 'POST',
|
|
333
|
-
headers: [{ name: 'Authorization', value: `Bearer ${token}` }],
|
|
334
|
-
} as RequestConfig,
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
await PostRepo.create({ values: { title: 't1' } });
|
|
338
|
-
|
|
339
|
-
await sleep(500);
|
|
340
|
-
|
|
341
|
-
const category = await db.getRepository('categories').findOne({});
|
|
342
|
-
|
|
343
|
-
const [execution] = await workflow.getExecutions();
|
|
344
|
-
expect(execution.status).toBe(EXECUTION_STATUS.RESOLVED);
|
|
345
|
-
const [job] = await execution.getJobs();
|
|
346
|
-
expect(job.status).toBe(JOB_STATUS.RESOLVED);
|
|
347
|
-
expect(job.result.data).toMatchObject({});
|
|
348
|
-
|
|
349
|
-
server.close();
|
|
350
|
-
});
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
describe('sync request', () => {
|
|
354
|
-
it('sync trigger', async () => {
|
|
355
|
-
const syncFlow = await WorkflowModel.create({
|
|
356
|
-
type: 'syncTrigger',
|
|
357
|
-
enabled: true,
|
|
358
|
-
});
|
|
359
|
-
await syncFlow.createNode({
|
|
360
|
-
type: 'request',
|
|
361
|
-
config: {
|
|
362
|
-
url: api.URL_DATA,
|
|
363
|
-
method: 'GET',
|
|
364
|
-
} as RequestConfig,
|
|
365
|
-
});
|
|
366
|
-
|
|
367
|
-
const workflowPlugin = app.pm.get(PluginWorkflow) as PluginWorkflow;
|
|
368
|
-
const processor = (await workflowPlugin.trigger(syncFlow, { data: { title: 't1' } })) as Processor;
|
|
369
|
-
|
|
370
|
-
const [execution] = await syncFlow.getExecutions();
|
|
371
|
-
expect(processor.execution.id).toEqual(execution.id);
|
|
372
|
-
expect(processor.execution.status).toEqual(execution.status);
|
|
373
|
-
expect(execution.status).toEqual(EXECUTION_STATUS.RESOLVED);
|
|
374
|
-
const [job] = await execution.getJobs();
|
|
375
|
-
expect(job.status).toEqual(JOB_STATUS.RESOLVED);
|
|
376
|
-
expect(job.result).toEqual({ meta: {}, data: {} });
|
|
377
|
-
});
|
|
378
|
-
});
|
|
379
|
-
});
|
package/src/server/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from './Plugin';
|