@nocobase/plugin-workflow-request 2.1.0-alpha.4 → 2.1.0-alpha.45
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/LICENSE +201 -661
- package/README.md +79 -10
- package/dist/client/RequestInstruction.d.ts +8 -0
- package/dist/client/index.js +1 -1
- package/dist/externalVersion.js +6 -5
- package/dist/locale/en-US.json +2 -1
- package/dist/locale/zh-CN.json +3 -1
- package/dist/node_modules/joi/dist/joi-browser.min.js +1 -0
- package/dist/node_modules/joi/lib/annotate.js +175 -0
- package/dist/node_modules/joi/lib/base.js +1069 -0
- package/dist/node_modules/joi/lib/cache.js +143 -0
- package/dist/node_modules/joi/lib/common.js +216 -0
- package/dist/node_modules/joi/lib/compile.js +283 -0
- package/dist/node_modules/joi/lib/errors.js +271 -0
- package/dist/node_modules/joi/lib/extend.js +312 -0
- package/dist/node_modules/joi/lib/index.d.ts +2365 -0
- package/dist/node_modules/joi/lib/index.js +1 -0
- package/dist/node_modules/joi/lib/manifest.js +476 -0
- package/dist/node_modules/joi/lib/messages.js +178 -0
- package/dist/node_modules/joi/lib/modify.js +267 -0
- package/dist/node_modules/joi/lib/ref.js +414 -0
- package/dist/node_modules/joi/lib/schemas.js +302 -0
- package/dist/node_modules/joi/lib/state.js +166 -0
- package/dist/node_modules/joi/lib/template.js +463 -0
- package/dist/node_modules/joi/lib/trace.js +346 -0
- package/dist/node_modules/joi/lib/types/alternatives.js +364 -0
- package/dist/node_modules/joi/lib/types/any.js +174 -0
- package/dist/node_modules/joi/lib/types/array.js +809 -0
- package/dist/node_modules/joi/lib/types/binary.js +100 -0
- package/dist/node_modules/joi/lib/types/boolean.js +150 -0
- package/dist/node_modules/joi/lib/types/date.js +233 -0
- package/dist/node_modules/joi/lib/types/function.js +93 -0
- package/dist/node_modules/joi/lib/types/keys.js +1067 -0
- package/dist/node_modules/joi/lib/types/link.js +168 -0
- package/dist/node_modules/joi/lib/types/number.js +363 -0
- package/dist/node_modules/joi/lib/types/object.js +22 -0
- package/dist/node_modules/joi/lib/types/string.js +850 -0
- package/dist/node_modules/joi/lib/types/symbol.js +102 -0
- package/dist/node_modules/joi/lib/validator.js +750 -0
- package/dist/node_modules/joi/lib/values.js +263 -0
- package/dist/node_modules/joi/node_modules/@hapi/topo/lib/index.d.ts +60 -0
- package/dist/node_modules/joi/node_modules/@hapi/topo/lib/index.js +225 -0
- package/dist/node_modules/joi/node_modules/@hapi/topo/package.json +30 -0
- package/dist/node_modules/joi/package.json +1 -0
- package/dist/server/RequestInstruction.d.ts +15 -5
- package/dist/server/RequestInstruction.js +106 -29
- package/package.json +4 -3
|
@@ -39,10 +39,11 @@ __export(RequestInstruction_exports, {
|
|
|
39
39
|
default: () => RequestInstruction_default
|
|
40
40
|
});
|
|
41
41
|
module.exports = __toCommonJS(RequestInstruction_exports);
|
|
42
|
-
var
|
|
42
|
+
var import_joi = __toESM(require("joi"));
|
|
43
43
|
var import_lodash = require("lodash");
|
|
44
44
|
var import_plugin_workflow = require("@nocobase/plugin-workflow");
|
|
45
45
|
var import_plugin_file_manager = __toESM(require("@nocobase/plugin-file-manager"));
|
|
46
|
+
var import_utils = require("@nocobase/utils");
|
|
46
47
|
function getContentTypeTransformer(mimeType, app) {
|
|
47
48
|
switch (mimeType) {
|
|
48
49
|
case "text/plain":
|
|
@@ -85,8 +86,30 @@ function getContentTypeTransformer(mimeType, app) {
|
|
|
85
86
|
};
|
|
86
87
|
}
|
|
87
88
|
}
|
|
88
|
-
|
|
89
|
+
function createInvalidUrlError(cause) {
|
|
90
|
+
if (cause instanceof TypeError && typeof cause.code !== "undefined") {
|
|
91
|
+
return cause;
|
|
92
|
+
}
|
|
93
|
+
const error = new TypeError("Invalid URL");
|
|
94
|
+
error.code = "ERR_INVALID_URL";
|
|
95
|
+
return error;
|
|
96
|
+
}
|
|
97
|
+
function validateUrl(url) {
|
|
98
|
+
if (!url) {
|
|
99
|
+
throw createInvalidUrlError();
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
const parsed = new URL(url);
|
|
103
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
104
|
+
throw createInvalidUrlError();
|
|
105
|
+
}
|
|
106
|
+
} catch (error) {
|
|
107
|
+
throw createInvalidUrlError(error);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
async function request(config, app, signal) {
|
|
89
111
|
const { url, method = "POST", contentType = "application/json", data, timeout = 5e3 } = config;
|
|
112
|
+
validateUrl(url);
|
|
90
113
|
const headers = (config.headers ?? []).reduce((result, header) => {
|
|
91
114
|
const name = (0, import_lodash.trim)(header.name);
|
|
92
115
|
if (name.toLowerCase() === "content-type") {
|
|
@@ -102,12 +125,13 @@ async function request(config, app) {
|
|
|
102
125
|
headers["Content-Type"] = contentType;
|
|
103
126
|
}
|
|
104
127
|
const transformer = getContentTypeTransformer(contentType, app);
|
|
105
|
-
return
|
|
128
|
+
return (0, import_utils.serverRequest)({
|
|
106
129
|
url: (0, import_lodash.trim)(url),
|
|
107
130
|
method,
|
|
108
131
|
headers,
|
|
109
132
|
params,
|
|
110
133
|
timeout,
|
|
134
|
+
signal,
|
|
111
135
|
...method.toLowerCase() !== "get" && data != null ? {
|
|
112
136
|
data: transformer ? await transformer(data) : data
|
|
113
137
|
} : {}
|
|
@@ -118,46 +142,91 @@ function responseSuccess(response, onlyData = false) {
|
|
|
118
142
|
status: response.status,
|
|
119
143
|
statusText: response.statusText,
|
|
120
144
|
headers: response.headers,
|
|
121
|
-
config: response.config,
|
|
122
145
|
data: response.data
|
|
123
146
|
};
|
|
124
147
|
}
|
|
125
148
|
function responseFailure(error) {
|
|
126
|
-
|
|
127
|
-
message: error.message
|
|
128
|
-
stack: error.stack
|
|
149
|
+
const result = {
|
|
150
|
+
message: error instanceof Error ? error.message : String(error)
|
|
129
151
|
};
|
|
130
|
-
if (error.
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
} else if (error.request) {
|
|
140
|
-
result = error.toJSON();
|
|
141
|
-
}
|
|
152
|
+
if (typeof (error == null ? void 0 : error.code) !== "undefined") {
|
|
153
|
+
result["code"] = error.code;
|
|
154
|
+
}
|
|
155
|
+
if ((error == null ? void 0 : error.isAxiosError) && error.response) {
|
|
156
|
+
Object.assign(result, {
|
|
157
|
+
status: error.response.status,
|
|
158
|
+
statusText: error.response.statusText,
|
|
159
|
+
data: error.response.data
|
|
160
|
+
});
|
|
142
161
|
}
|
|
143
162
|
return result;
|
|
144
163
|
}
|
|
164
|
+
function failureStatus(config, error) {
|
|
165
|
+
if (config.ignoreFail) {
|
|
166
|
+
return import_plugin_workflow.JOB_STATUS.RESOLVED;
|
|
167
|
+
}
|
|
168
|
+
return (error == null ? void 0 : error.code) === "ECONNABORTED" ? import_plugin_workflow.JOB_STATUS.ABORTED : import_plugin_workflow.JOB_STATUS.FAILED;
|
|
169
|
+
}
|
|
170
|
+
const METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE"];
|
|
171
|
+
const CONTENT_TYPES = [
|
|
172
|
+
"application/json",
|
|
173
|
+
"application/x-www-form-urlencoded",
|
|
174
|
+
"multipart/form-data",
|
|
175
|
+
"application/xml",
|
|
176
|
+
"text/plain"
|
|
177
|
+
];
|
|
178
|
+
function logFailureDebug(logger, error) {
|
|
179
|
+
if (!(error == null ? void 0 : error.isAxiosError)) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (error.response) {
|
|
183
|
+
logger.debug("request failed response details", {
|
|
184
|
+
status: error.response.status,
|
|
185
|
+
statusText: error.response.statusText,
|
|
186
|
+
data: error.response.data
|
|
187
|
+
});
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
logger.debug("request failed error details", responseFailure(error));
|
|
191
|
+
}
|
|
145
192
|
class RequestInstruction_default extends import_plugin_workflow.Instruction {
|
|
146
|
-
|
|
193
|
+
configSchema = import_joi.default.object({
|
|
194
|
+
url: import_joi.default.string(),
|
|
195
|
+
method: import_joi.default.string().valid(...METHODS),
|
|
196
|
+
contentType: import_joi.default.string().valid(...CONTENT_TYPES),
|
|
197
|
+
headers: import_joi.default.array().items(
|
|
198
|
+
import_joi.default.object({
|
|
199
|
+
name: import_joi.default.string(),
|
|
200
|
+
value: import_joi.default.string()
|
|
201
|
+
})
|
|
202
|
+
),
|
|
203
|
+
params: import_joi.default.array().items(
|
|
204
|
+
import_joi.default.object({
|
|
205
|
+
name: import_joi.default.string(),
|
|
206
|
+
value: import_joi.default.string()
|
|
207
|
+
})
|
|
208
|
+
),
|
|
209
|
+
data: import_joi.default.alternatives().try(import_joi.default.object(), import_joi.default.array(), import_joi.default.string()),
|
|
210
|
+
timeout: import_joi.default.number().integer().positive().default(5e3),
|
|
211
|
+
ignoreFail: import_joi.default.boolean().default(false),
|
|
212
|
+
onlyData: import_joi.default.boolean().default(false)
|
|
213
|
+
});
|
|
214
|
+
async run(node, prevJob, processor, options) {
|
|
147
215
|
const config = processor.getParsedValue(node.config, node.id);
|
|
148
216
|
const { workflow } = processor.execution;
|
|
149
217
|
const sync = this.workflow.isWorkflowSync(workflow);
|
|
150
218
|
if (sync) {
|
|
151
219
|
try {
|
|
152
|
-
const response = await request(config, this.workflow.app);
|
|
220
|
+
const response = await request(config, this.workflow.app, options == null ? void 0 : options.signal);
|
|
153
221
|
return {
|
|
154
222
|
status: import_plugin_workflow.JOB_STATUS.RESOLVED,
|
|
155
223
|
result: responseSuccess(response, config.onlyData)
|
|
156
224
|
};
|
|
157
225
|
} catch (error) {
|
|
226
|
+
logFailureDebug(this.workflow.app.logger, error);
|
|
158
227
|
return {
|
|
159
|
-
status: config
|
|
160
|
-
result: error
|
|
228
|
+
status: failureStatus(config, error),
|
|
229
|
+
result: responseFailure(error)
|
|
161
230
|
};
|
|
162
231
|
}
|
|
163
232
|
}
|
|
@@ -171,7 +240,7 @@ class RequestInstruction_default extends import_plugin_workflow.Instruction {
|
|
|
171
240
|
const jobDone = { status: import_plugin_workflow.JOB_STATUS.PENDING };
|
|
172
241
|
try {
|
|
173
242
|
processor.logger.info(`request (#${node.id}) sent to "${config.url}", waiting for response...`);
|
|
174
|
-
const response = await request(config, this.workflow.app);
|
|
243
|
+
const response = await request(config, this.workflow.app, options == null ? void 0 : options.signal);
|
|
175
244
|
processor.logger.info(`request (#${node.id}) response success, status: ${response.status}`);
|
|
176
245
|
jobDone.status = import_plugin_workflow.JOB_STATUS.RESOLVED;
|
|
177
246
|
jobDone.result = responseSuccess(response, config.onlyData);
|
|
@@ -187,14 +256,21 @@ class RequestInstruction_default extends import_plugin_workflow.Instruction {
|
|
|
187
256
|
} else {
|
|
188
257
|
processor.logger.error(`request (#${node.id}) failed unexpectedly: ${error.message}`);
|
|
189
258
|
}
|
|
190
|
-
|
|
259
|
+
logFailureDebug(processor.logger, error);
|
|
260
|
+
jobDone.status = failureStatus(config, error);
|
|
191
261
|
jobDone.result = responseFailure(error);
|
|
192
262
|
} finally {
|
|
193
263
|
const job = await this.workflow.app.db.getRepository("jobs").findOne({
|
|
194
264
|
filterByTk: id
|
|
195
265
|
});
|
|
196
|
-
job.
|
|
197
|
-
|
|
266
|
+
const execution = await job.getExecution();
|
|
267
|
+
if (!execution.status) {
|
|
268
|
+
job.set(jobDone);
|
|
269
|
+
job.execution = execution;
|
|
270
|
+
this.workflow.resume(job);
|
|
271
|
+
} else {
|
|
272
|
+
processor.logger.warn(`request (#${node.id}) result discarded because execution (${execution.id}) is ended`);
|
|
273
|
+
}
|
|
198
274
|
}
|
|
199
275
|
}
|
|
200
276
|
async resume(node, job, processor) {
|
|
@@ -212,9 +288,10 @@ class RequestInstruction_default extends import_plugin_workflow.Instruction {
|
|
|
212
288
|
result: responseSuccess(response, config.onlyData)
|
|
213
289
|
};
|
|
214
290
|
} catch (error) {
|
|
291
|
+
logFailureDebug(this.workflow.app.logger, error);
|
|
215
292
|
return {
|
|
216
|
-
status: config
|
|
217
|
-
result: error
|
|
293
|
+
status: failureStatus(config, error),
|
|
294
|
+
result: responseFailure(error)
|
|
218
295
|
};
|
|
219
296
|
}
|
|
220
297
|
}
|
package/package.json
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
"description": "Send HTTP requests to any HTTP service for data interaction in workflow.",
|
|
7
7
|
"description.ru-RU": "Отправляет HTTP-запросы к любому HTTP-сервису для взаимодействия с данными в рабочем процессе.",
|
|
8
8
|
"description.zh-CN": "可用于在工作流中向任意 HTTP 服务发送请求,进行数据交互。",
|
|
9
|
-
"version": "2.1.0-alpha.
|
|
10
|
-
"license": "
|
|
9
|
+
"version": "2.1.0-alpha.45",
|
|
10
|
+
"license": "Apache-2.0",
|
|
11
11
|
"main": "./dist/server/index.js",
|
|
12
12
|
"homepage": "https://docs.nocobase.com/handbook/workflow-request",
|
|
13
13
|
"homepage.ru-RU": "https://docs-ru.nocobase.com/handbook/workflow-request",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"antd": "5.x",
|
|
17
17
|
"axios": "^1.7.0",
|
|
18
|
+
"joi": "^17.13.3",
|
|
18
19
|
"react": "18.x",
|
|
19
20
|
"react-i18next": "^11.15.1"
|
|
20
21
|
},
|
|
@@ -26,7 +27,7 @@
|
|
|
26
27
|
"@nocobase/server": "2.x",
|
|
27
28
|
"@nocobase/test": "2.x"
|
|
28
29
|
},
|
|
29
|
-
"gitHead": "
|
|
30
|
+
"gitHead": "e9e24987e12d0ad10a5db8815b1e1b7b447f1938",
|
|
30
31
|
"keywords": [
|
|
31
32
|
"Workflow"
|
|
32
33
|
]
|