UNPKG

@tachybase/module-workflow

Version:

A powerful BPM tool that provides foundational support for business automation, with the capability to extend unlimited triggers and nodes.

208 lines (207 loc) 8.19 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var RequestInstruction_exports = {}; __export(RequestInstruction_exports, { default: () => RequestInstruction_default }); module.exports = __toCommonJS(RequestInstruction_exports); var import_node_fs = __toESM(require("node:fs")); var import_node_os = __toESM(require("node:os")); var import_node_path = __toESM(require("node:path")); var import_server = require("@tego/server"); var import_axios = __toESM(require("axios")); var import_form_data = __toESM(require("form-data")); var import_lodash = __toESM(require("lodash")); var import_mime_types = __toESM(require("mime-types")); var import__ = require("../.."); async function downloadToStream(resourceUrl, Headers, param, body) { try { const response = await (0, import_axios.default)({ method: "GET", url: resourceUrl, headers: Headers, params: param, data: body, responseType: "stream" }); const ext = import_mime_types.default.extension(Headers["Content-Type"]); let tempFileName; do { tempFileName = `${(0, import_server.uid)()}.${ext}`; } while (import_node_fs.default.existsSync(tempFileName)); const tempFilePath = import_node_path.default.join(import_node_os.default.tmpdir(), tempFileName); const writeStream = import_node_fs.default.createWriteStream(tempFilePath); response.data.pipe(writeStream); return new Promise((resolve, reject) => { writeStream.on("finish", () => { resolve(import_node_fs.default.createReadStream(tempFilePath)); }); writeStream.on("error", (error) => { import_node_fs.default.unlinkSync(tempFilePath); reject(error); }); }); } catch (error) { console.error("\u4E0B\u8F7D\u6587\u4EF6\u65F6\u51FA\u9519:", error); throw error; } } async function request(config, context) { var _a; const { token, origin } = context; const { method = "POST", needAuthorization = true, data, timeout = 5e3 } = config; const originUrl = ((_a = config.url) == null ? void 0 : _a.trim()) || ""; const url = originUrl.startsWith("http") ? originUrl : `${origin}${originUrl}`; let headers = (config.headers ?? []).reduce((result, header) => { return Object.assign(result, { [header.name]: header.value }); }, {}); const params = (config.params ?? []).reduce( (result, param) => Object.assign(result, { [param.name]: param.value }), {} ); const requestParams = { url, method, headers, params, data, timeout }; if (needAuthorization) { requestParams.headers = { Authorization: "Bearer " + token, ...headers }; } if (headers["Content-Type"] === "multipart/form-data") { const formData = new import_form_data.default(); for (const [key, value] of Object.entries(data)) { if (key === "file") { let { url: resourceUrl, params: resourceParams, headers: resourceHeader, body: resourceBody } = data[key]; resourceUrl = (resourceUrl == null ? void 0 : resourceUrl.trim()) || ""; if (resourceHeader["Content-Type"] === "multipart/form-data" && resourceBody) { const formData2 = new import_form_data.default(); Object.entries(resourceBody).forEach(([key2, value2]) => { formData2.append(key2, value2); }); config.data = formData2; } else { config.data = resourceBody; } const stream = await downloadToStream(resourceUrl, resourceHeader, resourceParams, resourceBody); formData.append("file", stream); headers = { ...formData.getHeaders() }; } else { formData.append(key, data[key]); } } requestParams.data = formData; } else { headers["Content-Type"] = "application/json"; } return import_axios.default.request(requestParams); } class RequestInstruction_default extends import__.Instruction { async run(node, prevJob, processor) { var _a, _b; const userId = import_lodash.default.get(processor.getScope(node.id), "$context.user.id", ""); const origin = import_server.Gateway.getInstance().runAtLoop; const token = this.workflow.app.authManager.jwt.sign({ userId }); const context = { token, origin }; const config = processor.getParsedValue(node.config, node.id); const requestParams = JSON.parse(JSON.stringify(config)); const { workflow } = processor.execution; const sync = this.workflow.isWorkflowSync(workflow); const loopData = prevJob.result; if (loopData["length"]) { config.params.push( { name: "loopLength", value: loopData["length"] }, { name: "loopIndex", value: loopData["index"] } ); } if (sync) { try { const response = await request(config, context); response.data = { requestParams: { ...requestParams, headers: { ...requestParams.headers, ...(_a = response.config) == null ? void 0 : _a.headers } }, ...response.data }; return { status: import__.JOB_STATUS.RESOLVED, result: response.data }; } catch (error) { return { status: import__.JOB_STATUS.FAILED, result: { requestParams: { ...requestParams, headers: { ...requestParams.headers, ...(_b = error.config) == null ? void 0 : _b.headers } }, error: error.isAxiosError ? error.toJSON() : error.message } }; } } const job = await processor.saveJob({ status: import__.JOB_STATUS.PENDING, nodeId: node.id, nodeKey: node.key, upstreamId: (prevJob == null ? void 0 : prevJob.id) ?? null }); request(config, context).then((response) => { var _a2; response.data = { requestParams: { ...requestParams, headers: { ...requestParams.headers, ...(_a2 = response.config) == null ? void 0 : _a2.headers } }, ...response.data }; job.set({ status: import__.JOB_STATUS.RESOLVED, result: response.data }); }).catch((error) => { var _a2; job.set({ status: import__.JOB_STATUS.FAILED, result: { requestParams: { ...requestParams, headers: { ...requestParams.headers, ...(_a2 = error.config) == null ? void 0 : _a2.headers } }, error: error.isAxiosError ? error.toJSON() : error.message } }); }).finally(() => { processor.logger.info(`request (#${node.id}) response received, status: ${job.get("status")}`); this.workflow.resume(job); }); processor.logger.info(`request (#${node.id}) sent to "${config.url}", waiting for response...`); return processor.exit(); } async resume(node, job, processor) { const { ignoreFail } = node.config; if (ignoreFail) { job.set("status", import__.JOB_STATUS.RESOLVED); } return job; } }