@nocobase/plugin-workflow 0.7.0-alpha.0
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 -0
- package/esm/actions/flow_nodes.d.ts +3 -0
- package/esm/actions/flow_nodes.js +139 -0
- package/esm/actions/flow_nodes.js.map +1 -0
- package/esm/actions/index.d.ts +1 -0
- package/esm/actions/index.js +8 -0
- package/esm/actions/index.js.map +1 -0
- package/esm/calculators/index.d.ts +38 -0
- package/esm/calculators/index.js +128 -0
- package/esm/calculators/index.js.map +1 -0
- package/esm/collections/executions.d.ts +3 -0
- package/esm/collections/executions.js +38 -0
- package/esm/collections/executions.js.map +1 -0
- package/esm/collections/flow_nodes.d.ts +3 -0
- package/esm/collections/flow_nodes.js +72 -0
- package/esm/collections/flow_nodes.js.map +1 -0
- package/esm/collections/jobs.d.ts +3 -0
- package/esm/collections/jobs.js +47 -0
- package/esm/collections/jobs.js.map +1 -0
- package/esm/collections/workflows.d.ts +3 -0
- package/esm/collections/workflows.js +63 -0
- package/esm/collections/workflows.js.map +1 -0
- package/esm/constants.d.ts +17 -0
- package/esm/constants.js +18 -0
- package/esm/constants.js.map +1 -0
- package/esm/index.d.ts +5 -0
- package/esm/index.js +6 -0
- package/esm/index.js.map +1 -0
- package/esm/instructions/calculation.d.ts +8 -0
- package/esm/instructions/calculation.js +55 -0
- package/esm/instructions/calculation.js.map +1 -0
- package/esm/instructions/condition.d.ts +5 -0
- package/esm/instructions/condition.js +99 -0
- package/esm/instructions/condition.js.map +1 -0
- package/esm/instructions/create.d.ts +8 -0
- package/esm/instructions/create.js +25 -0
- package/esm/instructions/create.js.map +1 -0
- package/esm/instructions/destroy.d.ts +8 -0
- package/esm/instructions/destroy.js +25 -0
- package/esm/instructions/destroy.js.map +1 -0
- package/esm/instructions/index.d.ts +15 -0
- package/esm/instructions/index.js +20 -0
- package/esm/instructions/index.js.map +1 -0
- package/esm/instructions/parallel.d.ts +13 -0
- package/esm/instructions/parallel.js +88 -0
- package/esm/instructions/parallel.js.map +1 -0
- package/esm/instructions/prompt.d.ts +7 -0
- package/esm/instructions/prompt.js +13 -0
- package/esm/instructions/prompt.js.map +1 -0
- package/esm/instructions/query.d.ts +8 -0
- package/esm/instructions/query.js +25 -0
- package/esm/instructions/query.js.map +1 -0
- package/esm/instructions/update.d.ts +8 -0
- package/esm/instructions/update.js +25 -0
- package/esm/instructions/update.js.map +1 -0
- package/esm/models/Execution.d.ts +50 -0
- package/esm/models/Execution.js +250 -0
- package/esm/models/Execution.js.map +1 -0
- package/esm/models/FlowNode.d.ts +17 -0
- package/esm/models/FlowNode.js +4 -0
- package/esm/models/FlowNode.js.map +1 -0
- package/esm/models/Job.d.ts +15 -0
- package/esm/models/Job.js +4 -0
- package/esm/models/Job.js.map +1 -0
- package/esm/models/Workflow.d.ts +27 -0
- package/esm/models/Workflow.js +72 -0
- package/esm/models/Workflow.js.map +1 -0
- package/esm/server.d.ts +5 -0
- package/esm/server.js +62 -0
- package/esm/server.js.map +1 -0
- package/esm/triggers/index.d.ts +9 -0
- package/esm/triggers/index.js +6 -0
- package/esm/triggers/index.js.map +1 -0
- package/esm/triggers/model.d.ts +12 -0
- package/esm/triggers/model.js +47 -0
- package/esm/triggers/model.js.map +1 -0
- package/lib/actions/flow_nodes.d.ts +3 -0
- package/lib/actions/flow_nodes.js +163 -0
- package/lib/actions/flow_nodes.js.map +1 -0
- package/lib/actions/index.d.ts +1 -0
- package/lib/actions/index.js +30 -0
- package/lib/actions/index.js.map +1 -0
- package/lib/calculators/index.d.ts +38 -0
- package/lib/calculators/index.js +132 -0
- package/lib/calculators/index.js.map +1 -0
- package/lib/collections/executions.d.ts +3 -0
- package/lib/collections/executions.js +40 -0
- package/lib/collections/executions.js.map +1 -0
- package/lib/collections/flow_nodes.d.ts +3 -0
- package/lib/collections/flow_nodes.js +74 -0
- package/lib/collections/flow_nodes.js.map +1 -0
- package/lib/collections/jobs.d.ts +3 -0
- package/lib/collections/jobs.js +49 -0
- package/lib/collections/jobs.js.map +1 -0
- package/lib/collections/workflows.d.ts +3 -0
- package/lib/collections/workflows.js +65 -0
- package/lib/collections/workflows.js.map +1 -0
- package/lib/constants.d.ts +17 -0
- package/lib/constants.js +21 -0
- package/lib/constants.js.map +1 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.js +23 -0
- package/lib/index.js.map +1 -0
- package/lib/instructions/calculation.d.ts +8 -0
- package/lib/instructions/calculation.js +57 -0
- package/lib/instructions/calculation.js.map +1 -0
- package/lib/instructions/condition.d.ts +5 -0
- package/lib/instructions/condition.js +120 -0
- package/lib/instructions/condition.js.map +1 -0
- package/lib/instructions/create.d.ts +8 -0
- package/lib/instructions/create.js +27 -0
- package/lib/instructions/create.js.map +1 -0
- package/lib/instructions/destroy.d.ts +8 -0
- package/lib/instructions/destroy.js +27 -0
- package/lib/instructions/destroy.js.map +1 -0
- package/lib/instructions/index.d.ts +15 -0
- package/lib/instructions/index.js +26 -0
- package/lib/instructions/index.js.map +1 -0
- package/lib/instructions/parallel.d.ts +13 -0
- package/lib/instructions/parallel.js +91 -0
- package/lib/instructions/parallel.js.map +1 -0
- package/lib/instructions/prompt.d.ts +7 -0
- package/lib/instructions/prompt.js +15 -0
- package/lib/instructions/prompt.js.map +1 -0
- package/lib/instructions/query.d.ts +8 -0
- package/lib/instructions/query.js +27 -0
- package/lib/instructions/query.js.map +1 -0
- package/lib/instructions/update.d.ts +8 -0
- package/lib/instructions/update.js +27 -0
- package/lib/instructions/update.js.map +1 -0
- package/lib/models/Execution.d.ts +50 -0
- package/lib/models/Execution.js +256 -0
- package/lib/models/Execution.js.map +1 -0
- package/lib/models/FlowNode.d.ts +17 -0
- package/lib/models/FlowNode.js +7 -0
- package/lib/models/FlowNode.js.map +1 -0
- package/lib/models/Job.d.ts +15 -0
- package/lib/models/Job.js +7 -0
- package/lib/models/Job.js.map +1 -0
- package/lib/models/Workflow.d.ts +27 -0
- package/lib/models/Workflow.js +78 -0
- package/lib/models/Workflow.js.map +1 -0
- package/lib/server.d.ts +5 -0
- package/lib/server.js +68 -0
- package/lib/server.js.map +1 -0
- package/lib/triggers/index.d.ts +9 -0
- package/lib/triggers/index.js +12 -0
- package/lib/triggers/index.js.map +1 -0
- package/lib/triggers/model.d.ts +12 -0
- package/lib/triggers/model.js +49 -0
- package/lib/triggers/model.js.map +1 -0
- package/package.json +28 -0
- package/tsconfig.build.json +9 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { Model } from '@nocobase/database';
|
|
11
|
+
import triggers from '../triggers';
|
|
12
|
+
import { EXECUTION_STATUS } from '../constants';
|
|
13
|
+
export default class WorkflowModel extends Model {
|
|
14
|
+
static mount() {
|
|
15
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
16
|
+
const collection = this.database.getCollection('workflows');
|
|
17
|
+
const workflows = yield collection.repository.find({
|
|
18
|
+
filter: { enabled: true },
|
|
19
|
+
});
|
|
20
|
+
workflows.forEach((workflow) => {
|
|
21
|
+
workflow.toggle();
|
|
22
|
+
});
|
|
23
|
+
this.addHook('afterCreate', (model) => model.toggle());
|
|
24
|
+
this.addHook('afterUpdate', (model) => model.toggle());
|
|
25
|
+
this.addHook('afterDestroy', (model) => model.toggle(false));
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
getHookId() {
|
|
29
|
+
return `workflow-${this.get('id')}`;
|
|
30
|
+
}
|
|
31
|
+
getTransaction(options) {
|
|
32
|
+
if (!this.useTransaction) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
return options.transaction && !options.transaction.finished
|
|
36
|
+
? options.transaction
|
|
37
|
+
: this.constructor.database.sequelize.transaction();
|
|
38
|
+
}
|
|
39
|
+
toggle(enable) {
|
|
40
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
41
|
+
const type = this.get('type');
|
|
42
|
+
const { on, off } = triggers.get(type);
|
|
43
|
+
if (typeof enable !== 'undefined' ? enable : this.get('enabled')) {
|
|
44
|
+
on.call(this, this.trigger.bind(this));
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
off.call(this);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
trigger(context, options) {
|
|
52
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
53
|
+
// `null` means not to trigger
|
|
54
|
+
if (context === null) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const transaction = yield this.getTransaction(options);
|
|
58
|
+
const execution = yield this.createExecution({
|
|
59
|
+
context,
|
|
60
|
+
status: EXECUTION_STATUS.STARTED,
|
|
61
|
+
useTransaction: this.useTransaction
|
|
62
|
+
}, { transaction });
|
|
63
|
+
execution.workflow = this;
|
|
64
|
+
yield execution.start({ transaction });
|
|
65
|
+
if (transaction && (!options.transaction || options.transaction.finished)) {
|
|
66
|
+
yield transaction.commit();
|
|
67
|
+
}
|
|
68
|
+
return execution;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=Workflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Workflow.js","sourceRoot":"","sources":["../../src/models/Workflow.ts"],"names":[],"mappings":"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","sourcesContent":["import { Database, Model } from '@nocobase/database';\nimport { HasManyCreateAssociationMixin, HasManyGetAssociationsMixin } from 'sequelize';\n\nimport triggers from '../triggers';\nimport { EXECUTION_STATUS } from '../constants';\nimport ExecutionModel from './Execution';\nimport FlowNodeModel from './FlowNode';\n\nexport default class WorkflowModel extends Model {\n declare static database: Database;\n\n declare id: number;\n declare title: string;\n declare enabled: boolean;\n declare description?: string;\n declare type: string;\n declare config: any;\n declare useTransaction: boolean;\n\n declare createdAt: Date;\n declare updatedAt: Date;\n\n declare nodes: FlowNodeModel[];\n declare getNodes: HasManyGetAssociationsMixin<FlowNodeModel>;\n declare createNode: HasManyCreateAssociationMixin<FlowNodeModel>;\n\n declare executions: ExecutionModel[];\n declare getExecutions: HasManyGetAssociationsMixin<ExecutionModel>;\n declare createExecution: HasManyCreateAssociationMixin<ExecutionModel>;\n\n static async mount() {\n const collection = this.database.getCollection('workflows');\n const workflows = await collection.repository.find({\n filter: { enabled: true },\n });\n\n workflows.forEach((workflow: WorkflowModel) => {\n workflow.toggle();\n });\n\n this.addHook('afterCreate', (model: WorkflowModel) => model.toggle());\n this.addHook('afterUpdate', (model: WorkflowModel) => model.toggle());\n this.addHook('afterDestroy', (model: WorkflowModel) => model.toggle(false));\n }\n\n getHookId() {\n return `workflow-${this.get('id')}`;\n }\n\n getTransaction(options) {\n if (!this.useTransaction) {\n return undefined;\n }\n\n return options.transaction && !options.transaction.finished\n ? options.transaction\n : (<typeof WorkflowModel>this.constructor).database.sequelize.transaction();\n }\n\n async toggle(enable?: boolean) {\n const type = this.get('type');\n const { on, off } = triggers.get(type);\n if (typeof enable !== 'undefined' ? enable : this.get('enabled')) {\n on.call(this, this.trigger.bind(this));\n } else {\n off.call(this);\n }\n }\n\n async trigger(context: Object, options) {\n // `null` means not to trigger\n if (context === null) {\n return;\n }\n\n const transaction = await this.getTransaction(options);\n\n const execution = await this.createExecution({\n context,\n status: EXECUTION_STATUS.STARTED,\n useTransaction: this.useTransaction\n }, { transaction });\n\n execution.workflow = this;\n\n await execution.start({ transaction });\n\n if (transaction && (!options.transaction || options.transaction.finished)) {\n await transaction.commit();\n }\n\n return execution;\n }\n}\n"]}
|
package/esm/server.d.ts
ADDED
package/esm/server.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import path from 'path';
|
|
11
|
+
import { Plugin } from '@nocobase/server';
|
|
12
|
+
import WorkflowModel from './models/Workflow';
|
|
13
|
+
import ExecutionModel from './models/Execution';
|
|
14
|
+
import actions from './actions';
|
|
15
|
+
export default class WorkflowPlugin extends Plugin {
|
|
16
|
+
load(options = {}) {
|
|
17
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
18
|
+
const { db } = this.app;
|
|
19
|
+
db.registerModels({
|
|
20
|
+
WorkflowModel,
|
|
21
|
+
ExecutionModel,
|
|
22
|
+
});
|
|
23
|
+
yield db.import({
|
|
24
|
+
directory: path.resolve(__dirname, 'collections'),
|
|
25
|
+
});
|
|
26
|
+
actions(this.app);
|
|
27
|
+
// [Life Cycle]:
|
|
28
|
+
// * load all workflows in db
|
|
29
|
+
// * add all hooks for enabled workflows
|
|
30
|
+
// * add hooks for create/update[enabled]/delete workflow to add/remove specific hooks
|
|
31
|
+
this.app.on('beforeStart', () => __awaiter(this, void 0, void 0, function* () {
|
|
32
|
+
const { model } = db.getCollection('workflows');
|
|
33
|
+
yield model.mount();
|
|
34
|
+
}));
|
|
35
|
+
// [Life Cycle]: initialize all necessary seed data
|
|
36
|
+
this.app.on('db.init', () => __awaiter(this, void 0, void 0, function* () { }));
|
|
37
|
+
// const [Automation, AutomationJob] = database.getModels(['automations', 'automations_jobs']);
|
|
38
|
+
// Automation.addHook('afterCreate', async (model: AutomationModel) => {
|
|
39
|
+
// model.get('enabled') && await model.loadJobs();
|
|
40
|
+
// });
|
|
41
|
+
// Automation.addHook('afterUpdate', async (model: AutomationModel) => {
|
|
42
|
+
// if (!model.changed('enabled' as any)) {
|
|
43
|
+
// return;
|
|
44
|
+
// }
|
|
45
|
+
// model.get('enabled') ? await model.loadJobs() : await model.cancelJobs();
|
|
46
|
+
// });
|
|
47
|
+
// Automation.addHook('beforeDestroy', async (model: AutomationModel) => {
|
|
48
|
+
// await model.cancelJobs();
|
|
49
|
+
// });
|
|
50
|
+
// AutomationJob.addHook('afterCreate', async (model: AutomationJobModel) => {
|
|
51
|
+
// await model.bootstrap();
|
|
52
|
+
// });
|
|
53
|
+
// AutomationJob.addHook('beforeDestroy', async (model: AutomationJobModel) => {
|
|
54
|
+
// await model.cancel();
|
|
55
|
+
// });
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
getName() {
|
|
59
|
+
return this.getPackageName(__dirname);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,OAAO,aAAa,MAAM,mBAAmB,CAAC;AAC9C,OAAO,cAAc,MAAM,oBAAoB,CAAC;AAChD,OAAO,OAAO,MAAM,WAAW,CAAC;AAEhC,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,MAAM;IAC1C,IAAI,CAAC,OAAO,GAAG,EAAE;;YACrB,MAAM,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC;YAExB,EAAE,CAAC,cAAc,CAAC;gBAChB,aAAa;gBACb,cAAc;aACf,CAAC,CAAC;YAEH,MAAM,EAAE,CAAC,MAAM,CAAC;gBACd,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,aAAa,CAAC;aAClD,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAElB,gBAAgB;YAChB,+BAA+B;YAC/B,0CAA0C;YAC1C,wFAAwF;YACxF,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,aAAa,EAAE,GAAS,EAAE;gBACpC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;gBAChD,MAAO,KAA8B,CAAC,KAAK,EAAE,CAAC;YAChD,CAAC,CAAA,CAAC,CAAC;YAEH,mDAAmD;YACnD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,GAAS,EAAE,gDAAE,CAAC,CAAA,CAAC,CAAC;YAEvC,+FAA+F;YAE/F,wEAAwE;YACxE,oDAAoD;YACpD,MAAM;YAEN,wEAAwE;YACxE,4CAA4C;YAC5C,cAAc;YACd,MAAM;YACN,8EAA8E;YAC9E,MAAM;YAEN,0EAA0E;YAC1E,8BAA8B;YAC9B,MAAM;YAEN,8EAA8E;YAC9E,6BAA6B;YAC7B,MAAM;YAEN,gFAAgF;YAChF,0BAA0B;YAC1B,MAAM;QACR,CAAC;KAAA;IAED,OAAO;QACL,OAAO,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IACxC,CAAC;CACF","sourcesContent":["import path from 'path';\n\nimport { Plugin } from '@nocobase/server';\n\nimport WorkflowModel from './models/Workflow';\nimport ExecutionModel from './models/Execution';\nimport actions from './actions';\n\nexport default class WorkflowPlugin extends Plugin {\n async load(options = {}) {\n const { db } = this.app;\n\n db.registerModels({\n WorkflowModel,\n ExecutionModel,\n });\n\n await db.import({\n directory: path.resolve(__dirname, 'collections'),\n });\n\n actions(this.app);\n\n // [Life Cycle]:\n // * load all workflows in db\n // * add all hooks for enabled workflows\n // * add hooks for create/update[enabled]/delete workflow to add/remove specific hooks\n this.app.on('beforeStart', async () => {\n const { model } = db.getCollection('workflows');\n await (model as typeof WorkflowModel).mount();\n });\n\n // [Life Cycle]: initialize all necessary seed data\n this.app.on('db.init', async () => {});\n\n // const [Automation, AutomationJob] = database.getModels(['automations', 'automations_jobs']);\n\n // Automation.addHook('afterCreate', async (model: AutomationModel) => {\n // model.get('enabled') && await model.loadJobs();\n // });\n\n // Automation.addHook('afterUpdate', async (model: AutomationModel) => {\n // if (!model.changed('enabled' as any)) {\n // return;\n // }\n // model.get('enabled') ? await model.loadJobs() : await model.cancelJobs();\n // });\n\n // Automation.addHook('beforeDestroy', async (model: AutomationModel) => {\n // await model.cancelJobs();\n // });\n\n // AutomationJob.addHook('afterCreate', async (model: AutomationJobModel) => {\n // await model.bootstrap();\n // });\n\n // AutomationJob.addHook('beforeDestroy', async (model: AutomationJobModel) => {\n // await model.cancel();\n // });\n }\n\n getName(): string {\n return this.getPackageName(__dirname);\n }\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Registry } from '@nocobase/utils';
|
|
2
|
+
import WorkflowModel from '../models/Workflow';
|
|
3
|
+
export interface Trigger {
|
|
4
|
+
name: string;
|
|
5
|
+
on(this: WorkflowModel, callback: Function): void;
|
|
6
|
+
off(this: WorkflowModel): void;
|
|
7
|
+
}
|
|
8
|
+
export declare const triggers: Registry<Trigger>;
|
|
9
|
+
export default triggers;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/triggers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,OAAO,YAAY,MAAM,SAAS,CAAC;AAQnC,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAW,CAAC;AAEhD,eAAe,QAAQ,CAAC;AAExB,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC","sourcesContent":["import { Registry } from '@nocobase/utils';\nimport WorkflowModel from '../models/Workflow';\nimport modelTrigger from './model';\n\nexport interface Trigger {\n name: string;\n on(this: WorkflowModel, callback: Function): void;\n off(this: WorkflowModel): void;\n}\n\nexport const triggers = new Registry<Trigger>();\n\nexport default triggers;\n\ntriggers.register(modelTrigger.name, modelTrigger);\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import WorkflowModel from "../models/Workflow";
|
|
2
|
+
export interface ModelChangeTriggerConfig {
|
|
3
|
+
collection: string;
|
|
4
|
+
mode: number;
|
|
5
|
+
filter: any;
|
|
6
|
+
}
|
|
7
|
+
declare const _default: {
|
|
8
|
+
name: string;
|
|
9
|
+
on(this: WorkflowModel, callback: Function): void;
|
|
10
|
+
off(this: WorkflowModel): void;
|
|
11
|
+
};
|
|
12
|
+
export default _default;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
const MODE_BITMAP = {
|
|
2
|
+
CREATE: 1,
|
|
3
|
+
UPDATE: 2,
|
|
4
|
+
DESTROY: 4
|
|
5
|
+
};
|
|
6
|
+
const MODE_BITMAP_EVENTS = new Map();
|
|
7
|
+
MODE_BITMAP_EVENTS.set(MODE_BITMAP.CREATE, 'afterCreate');
|
|
8
|
+
MODE_BITMAP_EVENTS.set(MODE_BITMAP.UPDATE, 'afterUpdate');
|
|
9
|
+
MODE_BITMAP_EVENTS.set(MODE_BITMAP.DESTROY, 'afterDestroy');
|
|
10
|
+
export default {
|
|
11
|
+
name: 'model',
|
|
12
|
+
on(callback) {
|
|
13
|
+
const { database } = this.constructor;
|
|
14
|
+
const { collection, mode, filter } = this.config;
|
|
15
|
+
const Collection = database.getCollection(collection);
|
|
16
|
+
if (!Collection) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
// async function, should return promise
|
|
20
|
+
const handler = (data, options) => {
|
|
21
|
+
if (filter) {
|
|
22
|
+
// TODO: check all conditions in filter against data
|
|
23
|
+
}
|
|
24
|
+
return callback({ data: data.get() }, options);
|
|
25
|
+
};
|
|
26
|
+
// TODO: duplication when mode change should be considered
|
|
27
|
+
for (let [key, event] of MODE_BITMAP_EVENTS.entries()) {
|
|
28
|
+
if (mode & key) {
|
|
29
|
+
Collection.model.addHook(event, this.getHookId(), handler);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
off() {
|
|
34
|
+
const { database } = this.constructor;
|
|
35
|
+
const { collection, mode } = this.config;
|
|
36
|
+
const Collection = database.getCollection(collection);
|
|
37
|
+
if (!Collection) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
for (let [key, event] of MODE_BITMAP_EVENTS.entries()) {
|
|
41
|
+
if (mode & key) {
|
|
42
|
+
Collection.model.removeHook(event, this.getHookId());
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/triggers/model.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,GAAG;IAClB,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,CAAC;IACT,OAAO,EAAE,CAAC;CACX,CAAC;AAEF,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAE,CAAC;AACrC,kBAAkB,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAC1D,kBAAkB,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAC1D,kBAAkB,CAAC,GAAG,CAAC,WAAW,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;AAE5D,eAAe;IACb,IAAI,EAAE,OAAO;IACb,EAAE,CAAsB,QAAkB;QACxC,MAAM,EAAE,QAAQ,EAAE,GAAyB,IAAI,CAAC,WAAW,CAAC;QAC5D,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;QACjD,MAAM,UAAU,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;QACtD,IAAI,CAAC,UAAU,EAAE;YACf,OAAO;SACR;QACD,wCAAwC;QACxC,MAAM,OAAO,GAAG,CAAC,IAAS,EAAE,OAAO,EAAE,EAAE;YACrC,IAAI,MAAM,EAAE;gBACV,oDAAoD;aACrD;YACD,OAAO,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;QACjD,CAAC,CAAC;QACF,0DAA0D;QAC1D,KAAK,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,kBAAkB,CAAC,OAAO,EAAE,EAAE;YACrD,IAAI,IAAI,GAAG,GAAG,EAAE;gBACd,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,EAAE,OAAO,CAAC,CAAC;aAC5D;SACF;IACH,CAAC;IACD,GAAG;QACD,MAAM,EAAE,QAAQ,EAAE,GAAyB,IAAI,CAAC,WAAW,CAAC;QAC5D,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;QACzC,MAAM,UAAU,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;QACtD,IAAI,CAAC,UAAU,EAAE;YACf,OAAO;SACR;QACD,KAAK,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,kBAAkB,CAAC,OAAO,EAAE,EAAE;YACrD,IAAI,IAAI,GAAG,GAAG,EAAE;gBACd,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;aACtD;SACF;IACH,CAAC;CACF,CAAA","sourcesContent":["import WorkflowModel from \"../models/Workflow\";\n\nexport interface ModelChangeTriggerConfig {\n collection: string;\n mode: number;\n // TODO: ICondition\n filter: any;\n}\n\nconst MODE_BITMAP = {\n CREATE: 1,\n UPDATE: 2,\n DESTROY: 4\n};\n\nconst MODE_BITMAP_EVENTS = new Map();\nMODE_BITMAP_EVENTS.set(MODE_BITMAP.CREATE, 'afterCreate');\nMODE_BITMAP_EVENTS.set(MODE_BITMAP.UPDATE, 'afterUpdate');\nMODE_BITMAP_EVENTS.set(MODE_BITMAP.DESTROY, 'afterDestroy');\n\nexport default {\n name: 'model',\n on(this: WorkflowModel, callback: Function) {\n const { database } = <typeof WorkflowModel>this.constructor;\n const { collection, mode, filter } = this.config;\n const Collection = database.getCollection(collection);\n if (!Collection) {\n return;\n }\n // async function, should return promise\n const handler = (data: any, options) => {\n if (filter) {\n // TODO: check all conditions in filter against data\n }\n return callback({ data: data.get() }, options);\n };\n // TODO: duplication when mode change should be considered\n for (let [key, event] of MODE_BITMAP_EVENTS.entries()) {\n if (mode & key) {\n Collection.model.addHook(event, this.getHookId(), handler);\n }\n }\n },\n off(this: WorkflowModel) {\n const { database } = <typeof WorkflowModel>this.constructor;\n const { collection, mode } = this.config;\n const Collection = database.getCollection(collection);\n if (!Collection) {\n return;\n }\n for (let [key, event] of MODE_BITMAP_EVENTS.entries()) {\n if (mode & key) {\n Collection.model.removeHook(event, this.getHookId());\n }\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
22
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
23
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
24
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
25
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
26
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
27
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
+
exports.destroy = exports.create = void 0;
|
|
32
|
+
const sequelize_1 = require("sequelize");
|
|
33
|
+
const actions_1 = __importStar(require("@nocobase/actions"));
|
|
34
|
+
function create(context, next) {
|
|
35
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
+
return actions_1.default.create(context, () => __awaiter(this, void 0, void 0, function* () {
|
|
37
|
+
const { body: instance, db } = context;
|
|
38
|
+
const repository = actions_1.utils.getRepositoryFromParams(context);
|
|
39
|
+
if (!instance.upstreamId) {
|
|
40
|
+
const previousHead = yield repository.findOne({
|
|
41
|
+
filter: {
|
|
42
|
+
id: {
|
|
43
|
+
$ne: instance.id
|
|
44
|
+
},
|
|
45
|
+
upstreamId: null
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
if (previousHead) {
|
|
49
|
+
yield previousHead.setUpstream(instance);
|
|
50
|
+
yield instance.setDownstream(previousHead);
|
|
51
|
+
instance.set('downstream', previousHead);
|
|
52
|
+
}
|
|
53
|
+
return next();
|
|
54
|
+
}
|
|
55
|
+
const upstream = yield instance.getUpstream();
|
|
56
|
+
if (instance.branchIndex == null) {
|
|
57
|
+
const downstream = yield upstream.getDownstream();
|
|
58
|
+
if (downstream) {
|
|
59
|
+
yield downstream.setUpstream(instance);
|
|
60
|
+
yield instance.setDownstream(downstream);
|
|
61
|
+
instance.set('downstream', downstream);
|
|
62
|
+
}
|
|
63
|
+
yield upstream.update({
|
|
64
|
+
downstreamId: instance.id
|
|
65
|
+
});
|
|
66
|
+
upstream.set('downstream', instance);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
const [downstream] = yield upstream.getBranches({
|
|
70
|
+
where: {
|
|
71
|
+
id: {
|
|
72
|
+
[sequelize_1.Op.ne]: instance.id
|
|
73
|
+
},
|
|
74
|
+
branchIndex: instance.branchIndex
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
if (downstream) {
|
|
78
|
+
yield downstream.update({
|
|
79
|
+
upstreamId: instance.id,
|
|
80
|
+
branchIndex: null
|
|
81
|
+
});
|
|
82
|
+
yield instance.setDownstream(downstream);
|
|
83
|
+
instance.set('downstream', downstream);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
instance.set('upstream', upstream);
|
|
87
|
+
yield next();
|
|
88
|
+
}));
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
exports.create = create;
|
|
92
|
+
function searchBranchNodes(nodes, from) {
|
|
93
|
+
const branchHeads = nodes
|
|
94
|
+
.filter((item) => item.upstreamId === from.id && item.branchIndex != null);
|
|
95
|
+
return branchHeads.reduce((flatten, head) => flatten.concat(searchBranchDownstreams(nodes, head)), []);
|
|
96
|
+
}
|
|
97
|
+
function searchBranchDownstreams(nodes, from) {
|
|
98
|
+
let result = [];
|
|
99
|
+
for (let search = from; search; search = search.downstream) {
|
|
100
|
+
result = [...result, search, ...searchBranchNodes(nodes, search)];
|
|
101
|
+
}
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
function destroy(context, next) {
|
|
105
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
106
|
+
const repository = actions_1.utils.getRepositoryFromParams(context);
|
|
107
|
+
const { db } = context;
|
|
108
|
+
const { filterByTk } = context.action.params;
|
|
109
|
+
context.body = yield db.sequelize.transaction((transaction) => __awaiter(this, void 0, void 0, function* () {
|
|
110
|
+
const fields = ['id', 'upstreamId', 'downstreamId', 'branchIndex'];
|
|
111
|
+
const instance = yield repository.findOne({
|
|
112
|
+
filterByTk,
|
|
113
|
+
fields: [...fields, 'workflowId'],
|
|
114
|
+
appends: ['upstream', 'downstream'],
|
|
115
|
+
transaction
|
|
116
|
+
});
|
|
117
|
+
const { upstream, downstream } = instance.get();
|
|
118
|
+
if (upstream && upstream.downstreamId === instance.id) {
|
|
119
|
+
yield upstream.update({
|
|
120
|
+
downstreamId: instance.downstreamId
|
|
121
|
+
}, { transaction });
|
|
122
|
+
}
|
|
123
|
+
if (downstream) {
|
|
124
|
+
yield downstream.update({
|
|
125
|
+
upstreamId: instance.upstreamId,
|
|
126
|
+
branchIndex: instance.branchIndex
|
|
127
|
+
}, { transaction });
|
|
128
|
+
}
|
|
129
|
+
const nodes = yield repository.find({
|
|
130
|
+
filter: {
|
|
131
|
+
workflowId: instance.workflowId
|
|
132
|
+
},
|
|
133
|
+
fields,
|
|
134
|
+
transaction
|
|
135
|
+
});
|
|
136
|
+
const nodesMap = new Map();
|
|
137
|
+
// make map
|
|
138
|
+
nodes.forEach(item => {
|
|
139
|
+
nodesMap.set(item.id, item);
|
|
140
|
+
});
|
|
141
|
+
// overwrite
|
|
142
|
+
nodesMap.set(instance.id, instance);
|
|
143
|
+
// make linked list
|
|
144
|
+
nodes.forEach(item => {
|
|
145
|
+
if (item.upstreamId) {
|
|
146
|
+
item.upstream = nodesMap.get(item.upstreamId);
|
|
147
|
+
}
|
|
148
|
+
if (item.downstreamId) {
|
|
149
|
+
item.downstream = nodesMap.get(item.downstreamId);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
const branchNodes = searchBranchNodes(nodes, instance);
|
|
153
|
+
yield repository.destroy({
|
|
154
|
+
filterByTk: [instance.id, ...branchNodes.map(item => item.id)],
|
|
155
|
+
transaction
|
|
156
|
+
});
|
|
157
|
+
return instance;
|
|
158
|
+
}));
|
|
159
|
+
yield next();
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
exports.destroy = destroy;
|
|
163
|
+
//# sourceMappingURL=flow_nodes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow_nodes.js","sourceRoot":"","sources":["../../src/actions/flow_nodes.ts"],"names":[],"mappings":"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","sourcesContent":["import { Op } from 'sequelize';\nimport actions, { Context, utils } from '@nocobase/actions';\n\nexport async function create(context: Context, next) {\n return actions.create(context, async () => {\n const { body: instance, db } = context;\n const repository = utils.getRepositoryFromParams(context);\n\n if (!instance.upstreamId) {\n const previousHead = await repository.findOne({\n filter: {\n id: {\n $ne: instance.id\n },\n upstreamId: null\n }\n });\n if (previousHead) {\n await previousHead.setUpstream(instance);\n await instance.setDownstream(previousHead);\n instance.set('downstream', previousHead);\n }\n return next();\n }\n\n const upstream = await instance.getUpstream();\n\n if (instance.branchIndex == null) {\n const downstream = await upstream.getDownstream();\n\n if (downstream) {\n await downstream.setUpstream(instance);\n await instance.setDownstream(downstream);\n instance.set('downstream', downstream);\n }\n\n await upstream.update({\n downstreamId: instance.id\n });\n\n upstream.set('downstream', instance);\n } else {\n const [downstream] = await upstream.getBranches({\n where: {\n id: {\n [Op.ne]: instance.id\n },\n branchIndex: instance.branchIndex\n }\n });\n\n if (downstream) {\n await downstream.update({\n upstreamId: instance.id,\n branchIndex: null\n });\n await instance.setDownstream(downstream);\n instance.set('downstream', downstream);\n }\n }\n\n instance.set('upstream', upstream);\n\n await next();\n });\n}\n\nfunction searchBranchNodes(nodes, from): any[] {\n const branchHeads = nodes\n .filter((item: any) => item.upstreamId === from.id && item.branchIndex != null);\n return branchHeads.reduce((flatten: any[], head) => flatten.concat(searchBranchDownstreams(nodes, head)), []) as any[];\n}\n\nfunction searchBranchDownstreams(nodes, from) {\n let result = [];\n for (let search = from; search; search = search.downstream) {\n result = [...result, search, ...searchBranchNodes(nodes, search)];\n }\n return result;\n}\n\nexport async function destroy(context: Context, next) {\n const repository = utils.getRepositoryFromParams(context);\n const { db } = context;\n const { filterByTk } = context.action.params;\n\n context.body = await db.sequelize.transaction(async transaction => {\n const fields = ['id', 'upstreamId', 'downstreamId', 'branchIndex'];\n const instance = await repository.findOne({\n filterByTk,\n fields: [...fields, 'workflowId'],\n appends: ['upstream', 'downstream'],\n transaction\n });\n const { upstream, downstream } = instance.get();\n\n if (upstream && upstream.downstreamId === instance.id) {\n await upstream.update({\n downstreamId: instance.downstreamId\n }, { transaction });\n }\n\n if (downstream) {\n await downstream.update({\n upstreamId: instance.upstreamId,\n branchIndex: instance.branchIndex\n }, { transaction });\n }\n\n const nodes = await repository.find({\n filter: {\n workflowId: instance.workflowId\n },\n fields,\n transaction\n });\n const nodesMap = new Map();\n // make map\n nodes.forEach(item => {\n nodesMap.set(item.id, item);\n });\n // overwrite\n nodesMap.set(instance.id, instance);\n // make linked list\n nodes.forEach(item => {\n if (item.upstreamId) {\n item.upstream = nodesMap.get(item.upstreamId);\n }\n if (item.downstreamId) {\n item.downstream = nodesMap.get(item.downstreamId);\n }\n });\n\n const branchNodes = searchBranchNodes(nodes, instance);\n\n await repository.destroy({\n filterByTk: [instance.id, ...branchNodes.map(item => item.id)],\n transaction\n });\n\n return instance;\n });\n\n await next();\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function (app: any): void;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
const flow_nodes = __importStar(require("./flow_nodes"));
|
|
23
|
+
function make(name, mod) {
|
|
24
|
+
return Object.keys(mod).reduce((result, key) => (Object.assign(Object.assign({}, result), { [`${name}:${key}`]: mod[key] })), {});
|
|
25
|
+
}
|
|
26
|
+
function default_1(app) {
|
|
27
|
+
app.actions(Object.assign({}, make('flow_nodes', flow_nodes)));
|
|
28
|
+
}
|
|
29
|
+
exports.default = default_1;
|
|
30
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/actions/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA,yDAA2C;AAE3C,SAAS,IAAI,CAAC,IAAI,EAAE,GAAG;IACrB,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,iCAC3C,MAAM,KACT,CAAC,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,IAC5B,EAAE,EAAE,CAAC,CAAA;AACT,CAAC;AAED,mBAAwB,GAAG;IACzB,GAAG,CAAC,OAAO,mBACN,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,EACjC,CAAC;AACL,CAAC;AAJD,4BAIC","sourcesContent":["import * as flow_nodes from './flow_nodes';\n\nfunction make(name, mod) {\n return Object.keys(mod).reduce((result, key) => ({\n ...result,\n [`${name}:${key}`]: mod[key]\n }), {})\n}\n\nexport default function(app) {\n app.actions({\n ...make('flow_nodes', flow_nodes)\n });\n}\n"]}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Registry } from "@nocobase/utils";
|
|
2
|
+
import ExecutionModel from '../models/Execution';
|
|
3
|
+
import JobModel from '../models/Job';
|
|
4
|
+
export declare const calculators: Registry<Function>;
|
|
5
|
+
export default calculators;
|
|
6
|
+
export declare type OperandType = '$context' | '$input' | '$jobsMapByNodeId' | '$calculation';
|
|
7
|
+
export declare type ObjectGetterOptions = {
|
|
8
|
+
path?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare type JobGetterOptions = ObjectGetterOptions & {
|
|
11
|
+
nodeId: number;
|
|
12
|
+
};
|
|
13
|
+
export declare type CalculationOptions = {
|
|
14
|
+
calculator: string;
|
|
15
|
+
operands: Operand[];
|
|
16
|
+
};
|
|
17
|
+
export declare type ConstantOperand = {
|
|
18
|
+
type?: 'constant';
|
|
19
|
+
value: any;
|
|
20
|
+
};
|
|
21
|
+
export declare type ContextOperand = {
|
|
22
|
+
type: '$context';
|
|
23
|
+
options: ObjectGetterOptions;
|
|
24
|
+
};
|
|
25
|
+
export declare type InputOperand = {
|
|
26
|
+
type: '$input';
|
|
27
|
+
options: ObjectGetterOptions;
|
|
28
|
+
};
|
|
29
|
+
export declare type JobOperand = {
|
|
30
|
+
type: '$jobsMapByNodeId';
|
|
31
|
+
options: JobGetterOptions;
|
|
32
|
+
};
|
|
33
|
+
export declare type Calculation = {
|
|
34
|
+
type: '$calculation';
|
|
35
|
+
options: CalculationOptions;
|
|
36
|
+
};
|
|
37
|
+
export declare type Operand = ContextOperand | InputOperand | JobOperand | ConstantOperand | Calculation;
|
|
38
|
+
export declare function calculate(operand: Operand, lastJob: JobModel, execution: ExecutionModel): any;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.calculate = exports.calculators = void 0;
|
|
4
|
+
const lodash_1 = require("lodash");
|
|
5
|
+
const utils_1 = require("@nocobase/utils");
|
|
6
|
+
exports.calculators = new utils_1.Registry();
|
|
7
|
+
exports.default = exports.calculators;
|
|
8
|
+
// @deprecated
|
|
9
|
+
// HACK: if no path provided, return self
|
|
10
|
+
// @see https://github.com/lodash/lodash/pull/1270
|
|
11
|
+
// TODO(question): should add default value as lodash?
|
|
12
|
+
function get(object, path) {
|
|
13
|
+
return path == null || !path.length ? object : (0, lodash_1.get)(object, path);
|
|
14
|
+
}
|
|
15
|
+
// NOTE:
|
|
16
|
+
// this method could only be used in executing nodes.
|
|
17
|
+
// because type of 'job' need loaded jobs in runtime execution.
|
|
18
|
+
// or the execution should be prepared first.
|
|
19
|
+
function calculate(operand, lastJob, execution) {
|
|
20
|
+
switch (operand.type) {
|
|
21
|
+
// @Deprecated
|
|
22
|
+
// from execution context
|
|
23
|
+
case '$context':
|
|
24
|
+
return get(execution.context, operand.options.path);
|
|
25
|
+
// @Deprecated
|
|
26
|
+
// from last job (or input job)
|
|
27
|
+
case '$input':
|
|
28
|
+
return lastJob !== null && lastJob !== void 0 ? lastJob : get(lastJob.result, operand.options.path);
|
|
29
|
+
// @Deprecated
|
|
30
|
+
// from job in execution
|
|
31
|
+
case '$jobsMapByNodeId':
|
|
32
|
+
// assume jobs have been fetched from execution before
|
|
33
|
+
const job = execution.jobsMapByNodeId[operand.options.nodeId];
|
|
34
|
+
return job && get(job, operand.options.path);
|
|
35
|
+
case '$calculation':
|
|
36
|
+
const fn = exports.calculators.get(operand.options.calculator);
|
|
37
|
+
if (!fn) {
|
|
38
|
+
throw new Error(`no calculator function registered for "${operand.options.calculator}"`);
|
|
39
|
+
}
|
|
40
|
+
return fn(...operand.options.operands.map(item => calculate(item, lastJob, execution)));
|
|
41
|
+
// constant
|
|
42
|
+
default:
|
|
43
|
+
return operand.value;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.calculate = calculate;
|
|
47
|
+
// built-in functions
|
|
48
|
+
function equal(a, b) {
|
|
49
|
+
return a === b;
|
|
50
|
+
}
|
|
51
|
+
function notEqual(a, b) {
|
|
52
|
+
return a !== b;
|
|
53
|
+
}
|
|
54
|
+
function gt(a, b) {
|
|
55
|
+
return a > b;
|
|
56
|
+
}
|
|
57
|
+
function gte(a, b) {
|
|
58
|
+
return a >= b;
|
|
59
|
+
}
|
|
60
|
+
function lt(a, b) {
|
|
61
|
+
return a < b;
|
|
62
|
+
}
|
|
63
|
+
function lte(a, b) {
|
|
64
|
+
return a <= b;
|
|
65
|
+
}
|
|
66
|
+
exports.calculators.register('equal', equal);
|
|
67
|
+
exports.calculators.register('notEqual', notEqual);
|
|
68
|
+
exports.calculators.register('gt', gt);
|
|
69
|
+
exports.calculators.register('gte', gte);
|
|
70
|
+
exports.calculators.register('lt', lt);
|
|
71
|
+
exports.calculators.register('lte', lte);
|
|
72
|
+
exports.calculators.register('===', equal);
|
|
73
|
+
exports.calculators.register('!==', notEqual);
|
|
74
|
+
exports.calculators.register('>', gt);
|
|
75
|
+
exports.calculators.register('>=', gte);
|
|
76
|
+
exports.calculators.register('<', lt);
|
|
77
|
+
exports.calculators.register('<=', lte);
|
|
78
|
+
function add(...args) {
|
|
79
|
+
return args.reduce((sum, a) => sum + a, 0);
|
|
80
|
+
}
|
|
81
|
+
function minus(a, b) {
|
|
82
|
+
return a - b;
|
|
83
|
+
}
|
|
84
|
+
function multipe(...args) {
|
|
85
|
+
return args.reduce((result, a) => result * a, 1);
|
|
86
|
+
}
|
|
87
|
+
function divide(a, b) {
|
|
88
|
+
return a / b;
|
|
89
|
+
}
|
|
90
|
+
function mod(a, b) {
|
|
91
|
+
return a % b;
|
|
92
|
+
}
|
|
93
|
+
exports.calculators.register('add', add);
|
|
94
|
+
exports.calculators.register('minus', minus);
|
|
95
|
+
exports.calculators.register('multipe', multipe);
|
|
96
|
+
exports.calculators.register('divide', divide);
|
|
97
|
+
exports.calculators.register('mod', mod);
|
|
98
|
+
exports.calculators.register('+', add);
|
|
99
|
+
exports.calculators.register('-', minus);
|
|
100
|
+
exports.calculators.register('*', multipe);
|
|
101
|
+
exports.calculators.register('/', divide);
|
|
102
|
+
exports.calculators.register('%', mod);
|
|
103
|
+
function includes(a, b) {
|
|
104
|
+
return a.includes(b);
|
|
105
|
+
}
|
|
106
|
+
function notIncludes(a, b) {
|
|
107
|
+
return !a.includes(b);
|
|
108
|
+
}
|
|
109
|
+
function startsWith(a, b) {
|
|
110
|
+
return a.startsWith(b);
|
|
111
|
+
}
|
|
112
|
+
function notStartsWith(a, b) {
|
|
113
|
+
return !a.startsWith(b);
|
|
114
|
+
}
|
|
115
|
+
function endsWith(a, b) {
|
|
116
|
+
return a.endsWith(b);
|
|
117
|
+
}
|
|
118
|
+
function notEndsWith(a, b) {
|
|
119
|
+
return !a.endsWith(b);
|
|
120
|
+
}
|
|
121
|
+
exports.calculators.register('includes', includes);
|
|
122
|
+
exports.calculators.register('notIncludes', notIncludes);
|
|
123
|
+
exports.calculators.register('startsWith', startsWith);
|
|
124
|
+
exports.calculators.register('notStartsWith', notStartsWith);
|
|
125
|
+
exports.calculators.register('endsWith', endsWith);
|
|
126
|
+
exports.calculators.register('notEndsWith', notEndsWith);
|
|
127
|
+
function before(a, b) {
|
|
128
|
+
return a < b;
|
|
129
|
+
}
|
|
130
|
+
exports.calculators.register('now', () => new Date());
|
|
131
|
+
// TODO: add more common calculators
|
|
132
|
+
//# sourceMappingURL=index.js.map
|