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.

192 lines (191 loc) 7.34 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 CollectionTrigger_exports = {}; __export(CollectionTrigger_exports, { default: () => CollectionTrigger }); module.exports = __toCommonJS(CollectionTrigger_exports); var import_server = require("@tego/server"); var import__ = __toESM(require(".")); var import_utils = require("../utils"); const MODE_BITMAP = { CREATE: 1, UPDATE: 2, DESTROY: 4 }; const MODE_BITMAP_EVENTS = /* @__PURE__ */ new Map(); MODE_BITMAP_EVENTS.set(MODE_BITMAP.CREATE, "afterCreateWithAssociations"); MODE_BITMAP_EVENTS.set(MODE_BITMAP.UPDATE, "afterUpdateWithAssociations"); MODE_BITMAP_EVENTS.set(MODE_BITMAP.DESTROY, "afterDestroy"); function getHookId(workflow, type) { return `${type}#${workflow.id}`; } function getFieldRawName(collection, name) { const field = collection.getField(name); if (field && field.options.type === "belongsTo") { return field.options.foreignKey; } return name; } async function handler(workflow, data, options) { var _a, _b; const { condition, changed, mode, appends, blacklist } = workflow.config; const [dataSourceName, collectionName] = (0, import_server.parseCollectionName)(workflow.config.collection); const collection = (_a = this.workflow.app.dataSourceManager) == null ? void 0 : _a.dataSources.get(dataSourceName).collectionManager.getCollection(collectionName); const { transaction, context } = options; const { repository, filterTargetKey } = collection; if (changed && changed.length && changed.filter( (name) => !["linkTo", "hasOne", "hasMany", "belongsToMany"].includes(collection.getField(name).options.type) ).every((name) => !data.changedWithAssociations(getFieldRawName(collection, name)))) { return; } if (blacklist && blacklist.length) { const changedWithAssociations = data.changedWithAssociations(); const presetFields = ["createdBy", "createdById", "createdAt", "updatedBy", "updatedById", "updatedAt"]; if (changedWithAssociations) { const userFields = changedWithAssociations.filter( (field) => !presetFields.includes(field) && collection.getField(field) && !["linkTo", "hasOne", "hasMany", "belongsToMany"].includes(collection.getField(field).options.type) ); const allInBlacklist = userFields.every((name) => blacklist.includes(name)); if (allInBlacklist) { return; } } } if (condition && ((_b = condition.$and) == null ? void 0 : _b.length)) { const count = await repository.count({ filter: { $and: [condition, { [filterTargetKey]: data[filterTargetKey] }] }, context, transaction }); if (!count) { return; } } let result = data; if ((appends == null ? void 0 : appends.length) && !(mode & MODE_BITMAP.DESTROY)) { const includeFields = appends.reduce((set, field) => { set.add(field.split(".")[0]); set.add(field); return set; }, /* @__PURE__ */ new Set()); result = await repository.findOne({ filterByTk: data[filterTargetKey], appends: Array.from(includeFields), transaction }); } const json = (0, import_utils.toJSON)(result); if (workflow.sync) { await this.workflow.trigger( workflow, { data: json, stack: context == null ? void 0 : context.stack }, { transaction: this.workflow.useDataSourceTransaction(dataSourceName, transaction) } ); } else { this.workflow.trigger(workflow, { data: json, stack: context == null ? void 0 : context.stack }); } } class CollectionTrigger extends import__.default { constructor() { super(...arguments); this.events = /* @__PURE__ */ new Map(); } on(workflow) { var _a, _b; const { collection, mode } = workflow.config; if (!collection) { return; } const [dataSourceName, collectionName] = (0, import_server.parseCollectionName)(collection); const { db } = ((_b = (_a = this.workflow.app.dataSourceManager) == null ? void 0 : _a.dataSources.get(dataSourceName)) == null ? void 0 : _b.collectionManager) ?? {}; if (!db || !db.getCollection(collectionName)) { return; } for (const [key, type] of MODE_BITMAP_EVENTS.entries()) { const event = `${collectionName}.${type}`; const name = getHookId(workflow, `${collection}.${type}`); if (mode & key) { if (!this.events.has(name)) { const listener = handler.bind(this, workflow); this.events.set(name, listener); db.on(event, listener); } } else { const listener = this.events.get(name); if (listener) { db.off(event, listener); this.events.delete(name); } } } } off(workflow) { var _a; const { collection, mode } = workflow.config; if (!collection) { return; } const [dataSourceName, collectionName] = (0, import_server.parseCollectionName)(collection); const { db } = ((_a = this.workflow.app.dataSourceManager.dataSources.get(dataSourceName)) == null ? void 0 : _a.collectionManager) ?? {}; if (!db || !db.getCollection(collectionName)) { return; } for (const [key, type] of MODE_BITMAP_EVENTS.entries()) { const name = getHookId(workflow, `${collection}.${type}`); if (mode & key) { const listener = this.events.get(name); if (listener) { db.off(`${collectionName}.${type}`, listener); this.events.delete(name); } } } } async validateEvent(workflow, context, options) { if (context.stack) { const existed = await workflow.countExecutions({ where: { id: context.stack }, transaction: options.transaction }); if (existed) { this.workflow.getLogger(workflow.id).warn( `workflow ${workflow.id} has already been triggered in stack executions (${context.stack}), and newly triggering will be skipped.` ); return false; } } return true; } }