@logicflow/engine 0.0.8 → 0.0.10-beta.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/README.md +5 -2
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/es/EventEmitter.d.ts +34 -4
- package/es/EventEmitter.js +70 -48
- package/es/EventEmitter.js.map +1 -0
- package/es/FlowModel.d.ts +75 -73
- package/es/FlowModel.js +130 -173
- package/es/FlowModel.js.map +1 -0
- package/es/Scheduler.d.ts +50 -34
- package/es/Scheduler.js +134 -209
- package/es/Scheduler.js.map +1 -0
- package/es/constant/{constant.js → index.js} +8 -7
- package/es/constant/index.js.map +1 -0
- package/es/constant/logCode.js +29 -0
- package/es/constant/logCode.js.map +1 -0
- package/es/expression/brewserVm.d.ts +2 -0
- package/es/expression/brewserVm.js +30 -0
- package/es/expression/brewserVm.js.map +1 -0
- package/es/expression/index.d.ts +1 -1
- package/es/expression/index.js +16 -59
- package/es/expression/index.js.map +1 -0
- package/es/expression/nodeVm.d.ts +4 -2
- package/es/expression/nodeVm.js +10 -50
- package/es/expression/nodeVm.js.map +1 -0
- package/es/index.d.ts +135 -38
- package/es/index.js +93 -145
- package/es/index.js.map +1 -0
- package/es/nodes/base.d.ts +108 -0
- package/es/nodes/base.js +149 -0
- package/es/nodes/base.js.map +1 -0
- package/es/nodes/index.d.ts +3 -0
- package/es/nodes/index.js +4 -0
- package/es/nodes/index.js.map +1 -0
- package/es/nodes/{StartNode.d.ts → start.d.ts} +3 -2
- package/es/nodes/start.js +11 -0
- package/es/nodes/start.js.map +1 -0
- package/es/nodes/{TaskNode.d.ts → task.d.ts} +3 -2
- package/es/nodes/task.js +11 -0
- package/es/nodes/task.js.map +1 -0
- package/es/platform/browser/browserVm.d.ts +4 -0
- package/es/platform/browser/browserVm.js +44 -0
- package/es/platform/browser/browserVm.js.map +1 -0
- package/es/platform/browser/index.d.ts +4 -0
- package/es/platform/browser/index.js +23 -0
- package/es/platform/browser/index.js.map +1 -0
- package/es/platform/index.d.ts +1 -0
- package/es/platform/index.js +2 -0
- package/es/platform/index.js.map +1 -0
- package/es/platform/node/index.d.ts +4 -0
- package/es/platform/node/index.js +23 -0
- package/es/platform/node/index.js.map +1 -0
- package/es/platform/node/nodeVm.d.ts +1 -0
- package/es/platform/node/nodeVm.js +9 -0
- package/es/platform/node/nodeVm.js.map +1 -0
- package/es/recorder/index.d.ts +36 -10
- package/es/recorder/index.js +82 -135
- package/es/recorder/index.js.map +1 -0
- package/es/utils/global.d.ts +5 -0
- package/es/utils/global.js +27 -0
- package/es/utils/global.js.map +1 -0
- package/es/utils/id.js +14 -0
- package/es/utils/id.js.map +1 -0
- package/es/utils/index.d.ts +4 -0
- package/es/utils/index.js +5 -0
- package/es/utils/index.js.map +1 -0
- package/es/{util → utils}/storage.js +17 -16
- package/es/utils/storage.js.map +1 -0
- package/lib/EventEmitter.d.ts +37 -0
- package/lib/EventEmitter.js +94 -0
- package/lib/EventEmitter.js.map +1 -0
- package/lib/FlowModel.d.ts +146 -0
- package/lib/FlowModel.js +236 -0
- package/lib/FlowModel.js.map +1 -0
- package/lib/Scheduler.d.ts +78 -0
- package/lib/Scheduler.js +179 -0
- package/lib/Scheduler.js.map +1 -0
- package/lib/constant/index.d.ts +16 -0
- package/{cjs/constant/constant.js → lib/constant/index.js} +4 -3
- package/lib/constant/index.js.map +1 -0
- package/lib/constant/logCode.d.ts +12 -0
- package/{cjs/constant/LogCode.js → lib/constant/logCode.js} +16 -13
- package/lib/constant/logCode.js.map +1 -0
- package/lib/expression/brewserVm.d.ts +2 -0
- package/lib/expression/brewserVm.js +33 -0
- package/lib/expression/brewserVm.js.map +1 -0
- package/lib/expression/index.d.ts +2 -0
- package/lib/expression/index.js +20 -0
- package/lib/expression/index.js.map +1 -0
- package/lib/expression/nodeVm.d.ts +4 -0
- package/lib/expression/nodeVm.js +13 -0
- package/lib/expression/nodeVm.js.map +1 -0
- package/lib/index.d.ts +157 -0
- package/lib/index.js +159 -0
- package/lib/index.js.map +1 -0
- package/lib/nodes/base.d.ts +108 -0
- package/lib/nodes/base.js +152 -0
- package/lib/nodes/base.js.map +1 -0
- package/lib/nodes/index.d.ts +3 -0
- package/lib/nodes/index.js +7 -0
- package/lib/nodes/index.js.map +1 -0
- package/lib/nodes/start.d.ts +6 -0
- package/lib/nodes/start.js +15 -0
- package/lib/nodes/start.js.map +1 -0
- package/lib/nodes/task.d.ts +6 -0
- package/lib/nodes/task.js +15 -0
- package/lib/nodes/task.js.map +1 -0
- package/lib/platform/browser/browserVm.d.ts +4 -0
- package/lib/platform/browser/browserVm.js +49 -0
- package/lib/platform/browser/browserVm.js.map +1 -0
- package/lib/platform/browser/index.d.ts +4 -0
- package/lib/platform/browser/index.js +28 -0
- package/lib/platform/browser/index.js.map +1 -0
- package/lib/platform/index.d.ts +1 -0
- package/lib/platform/index.js +5 -0
- package/lib/platform/index.js.map +1 -0
- package/lib/platform/node/index.d.ts +4 -0
- package/lib/platform/node/index.js +28 -0
- package/lib/platform/node/index.js.map +1 -0
- package/lib/platform/node/nodeVm.d.ts +1 -0
- package/lib/platform/node/nodeVm.js +13 -0
- package/lib/platform/node/nodeVm.js.map +1 -0
- package/lib/recorder/index.d.ts +46 -0
- package/lib/recorder/index.js +117 -0
- package/lib/recorder/index.js.map +1 -0
- package/lib/utils/global.d.ts +5 -0
- package/lib/utils/global.js +31 -0
- package/lib/utils/global.js.map +1 -0
- package/lib/utils/id.d.ts +3 -0
- package/lib/utils/id.js +20 -0
- package/lib/utils/id.js.map +1 -0
- package/lib/utils/index.d.ts +4 -0
- package/lib/utils/index.js +9 -0
- package/lib/utils/index.js.map +1 -0
- package/lib/utils/storage.d.ts +7 -0
- package/{cjs/util → lib/utils}/storage.js +18 -17
- package/lib/utils/storage.js.map +1 -0
- package/package.json +30 -71
- package/src/EventEmitter.ts +103 -0
- package/src/FlowModel.ts +325 -0
- package/src/Scheduler.ts +244 -0
- package/src/constant/index.ts +23 -0
- package/src/constant/logCode.ts +34 -0
- package/src/expression/brewserVm.ts +36 -0
- package/src/expression/index.ts +17 -0
- package/src/expression/nodeVm.ts +14 -0
- package/src/index.ts +300 -0
- package/src/nodes/base.ts +234 -0
- package/src/nodes/index.ts +3 -0
- package/src/nodes/start.ts +8 -0
- package/src/nodes/task.ts +8 -0
- package/src/platform/browser/browserVm.ts +52 -0
- package/src/platform/browser/index.ts +28 -0
- package/src/platform/index.ts +1 -0
- package/src/platform/node/index.ts +28 -0
- package/src/platform/node/nodeVm.ts +12 -0
- package/src/recorder/index.ts +137 -0
- package/src/typings.d.ts +0 -0
- package/src/utils/global.ts +41 -0
- package/src/utils/id.ts +16 -0
- package/src/utils/index.ts +5 -0
- package/src/utils/storage.ts +55 -0
- package/cjs/EventEmitter.js +0 -70
- package/cjs/FlowModel.js +0 -277
- package/cjs/Scheduler.js +0 -252
- package/cjs/expression/browserVm.js +0 -81
- package/cjs/expression/index.js +0 -63
- package/cjs/expression/nodeVm.js +0 -53
- package/cjs/index.js +0 -210
- package/cjs/nodes/BaseNode.js +0 -252
- package/cjs/nodes/StartNode.js +0 -27
- package/cjs/nodes/TaskNode.js +0 -27
- package/cjs/recorder/index.js +0 -168
- package/cjs/util/ID.js +0 -16
- package/cjs/util/global.js +0 -32
- package/es/constant/LogCode.js +0 -28
- package/es/expression/browserVm.d.ts +0 -4
- package/es/expression/browserVm.js +0 -76
- package/es/nodes/BaseNode.d.ts +0 -110
- package/es/nodes/BaseNode.js +0 -250
- package/es/nodes/StartNode.js +0 -25
- package/es/nodes/TaskNode.js +0 -25
- package/es/util/ID.js +0 -13
- package/es/util/global.d.ts +0 -5
- package/es/util/global.js +0 -26
- package/lib/main.js +0 -1
- /package/es/constant/{constant.d.ts → index.d.ts} +0 -0
- /package/es/constant/{LogCode.d.ts → logCode.d.ts} +0 -0
- /package/es/{util/ID.d.ts → utils/id.d.ts} +0 -0
- /package/es/{util → utils}/storage.d.ts +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"id.js","sourceRoot":"","sources":["../../src/utils/id.ts"],"names":[],"mappings":";;;AAAA,+BAAmC;AAE5B,MAAM,YAAY,GAAG,GAAW,EAAE;IACvC,MAAM,IAAI,GAAG,IAAA,SAAM,GAAE,CAAA;IACrB,OAAO,QAAQ,IAAI,EAAE,CAAA;AACvB,CAAC,CAAA;AAHY,QAAA,YAAY,gBAGxB;AAEM,MAAM,cAAc,GAAG,GAAW,EAAE;IACzC,MAAM,IAAI,GAAG,IAAA,SAAM,GAAE,CAAA;IACrB,OAAO,UAAU,IAAI,EAAE,CAAA;AACzB,CAAC,CAAA;AAHY,QAAA,cAAc,kBAG1B;AAEM,MAAM,cAAc,GAAG,GAAW,EAAE;IACzC,MAAM,IAAI,GAAG,IAAA,SAAM,GAAE,CAAA;IACrB,OAAO,UAAU,IAAI,EAAE,CAAA;AACzB,CAAC,CAAA;AAHY,QAAA,cAAc,kBAG1B"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.storage = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const storage_1 = tslib_1.__importDefault(require("./storage"));
|
|
6
|
+
exports.storage = storage_1.default;
|
|
7
|
+
tslib_1.__exportStar(require("./global"), exports);
|
|
8
|
+
tslib_1.__exportStar(require("./id"), exports);
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":";;;;AAAA,gEAA+B;AAItB,kBAJF,iBAAO,CAIE;AAFhB,mDAAwB;AACxB,+CAAoB"}
|
|
@@ -3,45 +3,46 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
/**
|
|
4
4
|
* 存储执行记录
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
const global_1 = require("./global");
|
|
7
7
|
if (!global_1.globalScope.sessionStorage) {
|
|
8
|
-
|
|
8
|
+
const storage = {
|
|
9
9
|
data: {},
|
|
10
|
-
setItem
|
|
11
|
-
|
|
10
|
+
setItem(key, value) {
|
|
11
|
+
storage.data[key] = value;
|
|
12
12
|
},
|
|
13
|
-
getItem
|
|
14
|
-
return
|
|
13
|
+
getItem(key) {
|
|
14
|
+
return storage.data[key];
|
|
15
15
|
},
|
|
16
|
-
removeItem
|
|
17
|
-
delete
|
|
16
|
+
removeItem(key) {
|
|
17
|
+
delete storage.data[key];
|
|
18
18
|
},
|
|
19
|
-
clear
|
|
20
|
-
|
|
19
|
+
clear() {
|
|
20
|
+
storage.data = {};
|
|
21
21
|
},
|
|
22
22
|
};
|
|
23
|
-
global_1.globalScope.sessionStorage =
|
|
23
|
+
global_1.globalScope.sessionStorage = storage;
|
|
24
24
|
}
|
|
25
25
|
exports.default = {
|
|
26
|
-
setItem
|
|
26
|
+
setItem(key, value) {
|
|
27
27
|
if (typeof value === 'object') {
|
|
28
28
|
value = JSON.stringify(value);
|
|
29
29
|
}
|
|
30
30
|
global_1.globalScope.sessionStorage.setItem(key, value);
|
|
31
31
|
},
|
|
32
|
-
getItem
|
|
33
|
-
|
|
32
|
+
getItem(key) {
|
|
33
|
+
const value = global_1.globalScope.sessionStorage.getItem(key);
|
|
34
34
|
try {
|
|
35
35
|
return JSON.parse(value);
|
|
36
36
|
}
|
|
37
|
-
catch (
|
|
37
|
+
catch (error) {
|
|
38
38
|
return value;
|
|
39
39
|
}
|
|
40
40
|
},
|
|
41
|
-
removeItem
|
|
41
|
+
removeItem(key) {
|
|
42
42
|
global_1.globalScope.sessionStorage.removeItem(key);
|
|
43
43
|
},
|
|
44
|
-
clear
|
|
44
|
+
clear() {
|
|
45
45
|
global_1.globalScope.sessionStorage.clear();
|
|
46
46
|
},
|
|
47
47
|
};
|
|
48
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/utils/storage.ts"],"names":[],"mappings":";;AAAA;;GAEG;AACH,qCAAsC;AAEtC,IAAI,CAAC,oBAAW,CAAC,cAAc,EAAE;IAC/B,MAAM,OAAO,GAAG;QACd,IAAI,EAAE,EAA6B;QAEnC,OAAO,CAAC,GAAG,EAAE,KAAK;YAChB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;QAC3B,CAAC;QAED,OAAO,CAAC,GAAG;YACT,OAAO,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC1B,CAAC;QAED,UAAU,CAAC,GAAG;YACZ,OAAO,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC1B,CAAC;QAED,KAAK;YACH,OAAO,CAAC,IAAI,GAAG,EAAE,CAAA;QACnB,CAAC;KACF,CAAA;IAED,oBAAW,CAAC,cAAc,GAAG,OAAO,CAAA;CACrC;AAED,kBAAe;IACb,OAAO,CAAC,GAAG,EAAE,KAAK;QAChB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;YAC7B,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;SAC9B;QAED,oBAAW,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IAChD,CAAC;IAED,OAAO,CAAC,GAAG;QACT,MAAM,KAAK,GAAG,oBAAW,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACrD,IAAI;YACF,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;SACzB;QAAC,OAAO,KAAK,EAAE;YACd,OAAO,KAAK,CAAA;SACb;IACH,CAAC;IAED,UAAU,CAAC,GAAG;QACZ,oBAAW,CAAC,cAAc,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;IAC5C,CAAC;IAED,KAAK;QACH,oBAAW,CAAC,cAAc,CAAC,KAAK,EAAE,CAAA;IACpC,CAAC;CACF,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,90 +1,49 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@logicflow/engine",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10-beta.0",
|
|
4
4
|
"description": "a process engine for javascript",
|
|
5
|
-
"main": "
|
|
5
|
+
"main": "lib/index.js",
|
|
6
6
|
"module": "es/index.js",
|
|
7
|
-
"homepage": "https://docs.logic-flow.cn",
|
|
8
7
|
"types": "es/index.d.ts",
|
|
9
|
-
"repository": {
|
|
10
|
-
"type": "git",
|
|
11
|
-
"url": "https://github.com/didi/LogicFlow",
|
|
12
|
-
"directory": "packages/engine"
|
|
13
|
-
},
|
|
14
8
|
"browser": {
|
|
15
|
-
"
|
|
16
|
-
},
|
|
17
|
-
"license": "Apache-2.0",
|
|
18
|
-
"scripts": {
|
|
19
|
-
"dev": "cross-env NODE_ENV=development webpack-dev-server --client-log-level warning --config scripts/webpack.config.dev.js",
|
|
20
|
-
"types": "tsc -d --declarationDir ./types --outDir temp && rimraf -R temp",
|
|
21
|
-
"build:esm": "tsc --module esnext --target es5 --outDir ./es -d",
|
|
22
|
-
"build:cjs": "tsc --module commonjs --target es5 --outDir ./cjs",
|
|
23
|
-
"build:umd": "cross-env NODE_ENV=production webpack --config scripts/webpack.config.build.js",
|
|
24
|
-
"build": "rimraf ./es ./cjs ./lib && npm run build:esm & npm run build:cjs & npm run build:umd",
|
|
25
|
-
"publish-lib": "npm run build && npm publish",
|
|
26
|
-
"test": "jest",
|
|
27
|
-
"test:watch": "jest --watch"
|
|
9
|
+
"./es/platform/node/index.js": "./es/platform/browser/index.js"
|
|
28
10
|
},
|
|
29
|
-
"
|
|
11
|
+
"jsdeliver": "dist/index.js",
|
|
12
|
+
"unpkg": "dist/index.js",
|
|
30
13
|
"files": [
|
|
31
|
-
"
|
|
14
|
+
"dist",
|
|
32
15
|
"es",
|
|
33
16
|
"lib",
|
|
34
|
-
"
|
|
17
|
+
"src",
|
|
35
18
|
"readme.md"
|
|
36
19
|
],
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
20
|
+
"scripts": {
|
|
21
|
+
"test": "jest",
|
|
22
|
+
"clean:turbo": "rss",
|
|
23
|
+
"clean:build": "rss",
|
|
24
|
+
"clean": "rss",
|
|
25
|
+
"build:less": "rss",
|
|
26
|
+
"build:esm": "rss",
|
|
27
|
+
"build:cjs": "rss",
|
|
28
|
+
"build:umd": "rollup -c ./rollup.config.js --bundleConfigAsCjs",
|
|
29
|
+
"build:dev": "run-p -s build:cjs build:esm",
|
|
30
|
+
"build:watch": "rss",
|
|
31
|
+
"build:watch:esm": "rss",
|
|
32
|
+
"build:watch:cjs": "rss",
|
|
33
|
+
"build": "rss",
|
|
34
|
+
"prebuild": "rss"
|
|
45
35
|
},
|
|
46
36
|
"keywords": [
|
|
47
37
|
"logicflow",
|
|
48
38
|
"workflow",
|
|
49
|
-
"process"
|
|
50
|
-
"diagram"
|
|
39
|
+
"process engine"
|
|
51
40
|
],
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
"
|
|
56
|
-
"@babel/plugin-transform-react-jsx": "^7.10.4",
|
|
57
|
-
"@babel/preset-env": "^7.9.5",
|
|
58
|
-
"@babel/preset-typescript": "^7.9.0",
|
|
59
|
-
"@commitlint/config-conventional": "^8.3.4",
|
|
60
|
-
"@typescript-eslint/eslint-plugin": "^4.7.0",
|
|
61
|
-
"@typescript-eslint/parser": "^3.2.0",
|
|
62
|
-
"babel-core": "^7.0.0-bridge.0",
|
|
63
|
-
"babel-loader": "^8.1.0",
|
|
64
|
-
"babel-plugin-import": "^1.13.0",
|
|
65
|
-
"case-sensitive-paths-webpack-plugin": "^2.3.0",
|
|
66
|
-
"core-js": "^3.6.5",
|
|
67
|
-
"cross-env": "^7.0.2",
|
|
68
|
-
"css-loader": "^4.2.1",
|
|
69
|
-
"eslint": "^7.0.0",
|
|
70
|
-
"eslint-config-airbnb-typescript": "^9.0.0",
|
|
71
|
-
"eslint-plugin-import": "^2.22.0",
|
|
72
|
-
"eslint-plugin-jsx-a11y": "^6.3.1",
|
|
73
|
-
"eslint-plugin-react": "^7.20.6",
|
|
74
|
-
"eslint-plugin-standard": "^4.0.1",
|
|
75
|
-
"eslint-webpack-plugin": "^2.1.0",
|
|
76
|
-
"html-webpack-plugin": "^4.2.0",
|
|
77
|
-
"less-loader": "^6.0.0",
|
|
78
|
-
"prettier": "^2.2.1",
|
|
79
|
-
"rimraf": "^3.0.2",
|
|
80
|
-
"standard-version": "^9.0.0",
|
|
81
|
-
"style-loader": "^1.2.0",
|
|
82
|
-
"typescript": "^3.8.3",
|
|
83
|
-
"url-loader": "^4.1.0",
|
|
84
|
-
"webpack": "^4.43.0",
|
|
85
|
-
"webpack-bundle-analyzer": "^4.1.0",
|
|
86
|
-
"webpack-cli": "^3.3.11",
|
|
87
|
-
"webpack-dev-server": "^3.10.3"
|
|
41
|
+
"author": "Logicflow-Team",
|
|
42
|
+
"license": "Apache-2.0",
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"uuid": "^8.2.0"
|
|
88
45
|
},
|
|
89
|
-
"
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"tslib": "^2.6.1"
|
|
48
|
+
}
|
|
90
49
|
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
export interface EventType {
|
|
2
|
+
readonly callback: (params?: any) => void
|
|
3
|
+
readonly once: boolean
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export type EventArgs = Record<string, unknown>
|
|
7
|
+
export type EventsType = Record<string, EventType[]>
|
|
8
|
+
export type CallbackType = (...args: unknown[]) => void
|
|
9
|
+
|
|
10
|
+
export default class EventEmitter {
|
|
11
|
+
private _events: EventsType
|
|
12
|
+
constructor() {
|
|
13
|
+
this._events = {}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 添加一个监听事件
|
|
18
|
+
* @param evtKey 事件名称
|
|
19
|
+
* @param callback 回调方法
|
|
20
|
+
* @param once 是否触发一次
|
|
21
|
+
* @returns 当前 EventEmitter 实例
|
|
22
|
+
*/
|
|
23
|
+
on(evtKey: string, callback: CallbackType, once?: boolean) {
|
|
24
|
+
evtKey = evtKey.trim()
|
|
25
|
+
if (!this._events[evtKey]) {
|
|
26
|
+
this._events[evtKey] = []
|
|
27
|
+
}
|
|
28
|
+
this._events[evtKey].push({
|
|
29
|
+
callback,
|
|
30
|
+
once: !!once,
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 取消监听一个事件,或者一个 Channel
|
|
36
|
+
* @param evtKey
|
|
37
|
+
* @param callback
|
|
38
|
+
*/
|
|
39
|
+
off(evtKey: string, callback?: CallbackType) {
|
|
40
|
+
if (!evtKey) {
|
|
41
|
+
// evtKey 为空全部清除
|
|
42
|
+
this._events = {}
|
|
43
|
+
}
|
|
44
|
+
if (!callback) {
|
|
45
|
+
// evtKey 存在,callback 为空,清除事件所有方法
|
|
46
|
+
delete this._events[evtKey]
|
|
47
|
+
} else {
|
|
48
|
+
// evtKey 存在,callback 存在,清除匹配的
|
|
49
|
+
const events = this._events[evtKey] || []
|
|
50
|
+
let { length } = events
|
|
51
|
+
for (let i = 0; i < length; i++) {
|
|
52
|
+
if (events[i].callback === callback) {
|
|
53
|
+
events.splice(i, 1)
|
|
54
|
+
length--
|
|
55
|
+
i--
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (events.length === 0) {
|
|
59
|
+
delete this._events[evtKey]
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 主动触发事件
|
|
66
|
+
* @param evtKey 触发事件名称
|
|
67
|
+
* @param eventArgs 事件参数
|
|
68
|
+
*/
|
|
69
|
+
emit(evtKey: string, eventArgs: EventArgs) {
|
|
70
|
+
const events = this._events[evtKey] || []
|
|
71
|
+
// 实际的处理 emit 方法
|
|
72
|
+
const doEmit = (es) => {
|
|
73
|
+
let { length } = es
|
|
74
|
+
for (let i = 0; i < length; i++) {
|
|
75
|
+
if (!es[i]) {
|
|
76
|
+
// eslint-disable-next-line no-continue
|
|
77
|
+
continue
|
|
78
|
+
}
|
|
79
|
+
const { callback, once } = es[i]
|
|
80
|
+
if (once) {
|
|
81
|
+
es.splice(i, 1)
|
|
82
|
+
if (es.length === 0) {
|
|
83
|
+
delete this._events[evtKey]
|
|
84
|
+
}
|
|
85
|
+
length--
|
|
86
|
+
i--
|
|
87
|
+
}
|
|
88
|
+
callback.apply(this, [eventArgs])
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
doEmit(events)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* 获取当前所有事件
|
|
96
|
+
* @returns _events
|
|
97
|
+
*/
|
|
98
|
+
getEvents() {
|
|
99
|
+
return this._events
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export { EventEmitter }
|
package/src/FlowModel.ts
ADDED
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import { Engine } from '.'
|
|
2
|
+
import { Recorder } from './recorder'
|
|
3
|
+
import { Scheduler } from './Scheduler'
|
|
4
|
+
import { BaseNode } from './nodes'
|
|
5
|
+
import { createExecId } from './utils'
|
|
6
|
+
import {
|
|
7
|
+
EVENT_INSTANCE_COMPLETE,
|
|
8
|
+
EVENT_INSTANCE_INTERRUPTED,
|
|
9
|
+
EVENT_INSTANCE_ERROR,
|
|
10
|
+
} from './constant'
|
|
11
|
+
import { ErrorCode, getErrorMsg } from './constant/logCode'
|
|
12
|
+
|
|
13
|
+
export class FlowModel {
|
|
14
|
+
/**
|
|
15
|
+
* 流程支持的节点类型.
|
|
16
|
+
*/
|
|
17
|
+
nodeModelMap: Map<string, BaseNode.NodeConstructor>
|
|
18
|
+
/**
|
|
19
|
+
* 调度器,用于调度节点执行
|
|
20
|
+
*/
|
|
21
|
+
scheduler: Scheduler
|
|
22
|
+
/**
|
|
23
|
+
* 待执行的队列,当流程正在执行时,如果再次触发执行。那么会将执行参数放到队列中,等待上一次执行完成后再执行。
|
|
24
|
+
*/
|
|
25
|
+
executeList: Partial<FlowModel.ExecParam>[]
|
|
26
|
+
/**
|
|
27
|
+
* 当前正在执行的任务。当监听到调度器执行完成时,触发执行参数中的回调,告知外部执行完成。
|
|
28
|
+
*/
|
|
29
|
+
executingInstance?: FlowModel.ExecParam | null
|
|
30
|
+
/**
|
|
31
|
+
* 当前流程模型中的所有节点,边会被转换成节点的 incoming 和 outgoing 属性
|
|
32
|
+
*/
|
|
33
|
+
nodeConfigMap: Map<Engine.Key, BaseNode.NodeConfig> = new Map()
|
|
34
|
+
/**
|
|
35
|
+
* 当流程正在执行时,如果再次触发执行。那么会将执行参数放入到队列中,等待上一次执行完成后再执行。
|
|
36
|
+
*/
|
|
37
|
+
isRunning: boolean
|
|
38
|
+
/**
|
|
39
|
+
* 开始接地那类型,在执行流程时,会从这些节点开始执行
|
|
40
|
+
*/
|
|
41
|
+
startNodeType: string
|
|
42
|
+
/**
|
|
43
|
+
* 当前流程中开始节点组成的数组
|
|
44
|
+
*/
|
|
45
|
+
startNodes: BaseNode.NodeConfig[] = []
|
|
46
|
+
/**
|
|
47
|
+
* 用于存储全局数据,最终会传递给每个节点
|
|
48
|
+
*/
|
|
49
|
+
globalData: Record<string, unknown> = {}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 外部传入的上下文,最终会传递给每个节点
|
|
53
|
+
* 例如:
|
|
54
|
+
* const context = {
|
|
55
|
+
* request: {
|
|
56
|
+
* get: (url) => {
|
|
57
|
+
* return fetch(url);
|
|
58
|
+
* },
|
|
59
|
+
* },
|
|
60
|
+
* }
|
|
61
|
+
* 在节点内可以通过 this.context.request.get(url) 来调用。
|
|
62
|
+
*/
|
|
63
|
+
context: Record<string, unknown>
|
|
64
|
+
|
|
65
|
+
constructor({
|
|
66
|
+
nodeModelMap,
|
|
67
|
+
recorder,
|
|
68
|
+
context = {},
|
|
69
|
+
globalData = {},
|
|
70
|
+
startNodeType = 'StartNode',
|
|
71
|
+
}: FlowModel.IFlowModelProps) {
|
|
72
|
+
// 流程包含的节点类型 ??? 在 load 代码中又初始化了一遍,为什么要传进来
|
|
73
|
+
this.nodeModelMap = nodeModelMap
|
|
74
|
+
// 需要执行的队列
|
|
75
|
+
this.executeList = []
|
|
76
|
+
// 执行中的任务
|
|
77
|
+
this.executingInstance = null
|
|
78
|
+
// 外部传入的上下文,最终会传递给每个节点
|
|
79
|
+
this.context = context
|
|
80
|
+
// 用于存储全局数据,可以在流程中共享
|
|
81
|
+
this.globalData = globalData
|
|
82
|
+
// 开始节点类型,在执行流程时,会从这些节点开始执行
|
|
83
|
+
this.startNodeType = startNodeType
|
|
84
|
+
this.isRunning = false
|
|
85
|
+
this.scheduler = new Scheduler({
|
|
86
|
+
flowModel: this,
|
|
87
|
+
recorder,
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
this.scheduler.on(EVENT_INSTANCE_COMPLETE, (result) => {
|
|
91
|
+
this.onExecuteFinished(result)
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
this.scheduler.on(EVENT_INSTANCE_INTERRUPTED, (result) => {
|
|
95
|
+
this.onExecuteFinished(result)
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
this.scheduler.on(EVENT_INSTANCE_ERROR, (result) => {
|
|
99
|
+
this.onExecuteFinished(result)
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* 解析LogicFlow图数据,将nodes和edges转换成节点格式。
|
|
104
|
+
* 例如:
|
|
105
|
+
* graphData: {
|
|
106
|
+
* nodes: [
|
|
107
|
+
* { id: 'node1', type: 'StartNode', properties: {} },
|
|
108
|
+
* { id: 'node2', type: 'TaskNode', properties: {} },
|
|
109
|
+
* ],
|
|
110
|
+
* edges: [
|
|
111
|
+
* { id: 'edge1', sourceNodeId: 'node1', targetNodeId: 'node2', properties: {} },
|
|
112
|
+
* ]
|
|
113
|
+
* }
|
|
114
|
+
* 转换成:
|
|
115
|
+
* nodeConfigMap: {
|
|
116
|
+
* node1: {
|
|
117
|
+
* id: 'node1',
|
|
118
|
+
* type: 'StartNode',
|
|
119
|
+
* properties: {},
|
|
120
|
+
* incoming: [],
|
|
121
|
+
* outgoing: [{ id: 'edge1', properties: {}, target: 'node2' }]
|
|
122
|
+
* },
|
|
123
|
+
* node2: {
|
|
124
|
+
* id: 'node2',
|
|
125
|
+
* type: 'TaskNode',
|
|
126
|
+
* properties: {},
|
|
127
|
+
* incoming: [{ id: 'edge1', properties: {}, source: 'node1' }],
|
|
128
|
+
* outgoing: [],
|
|
129
|
+
* }
|
|
130
|
+
* }
|
|
131
|
+
* 此格式方便后续执行时,根据节点id快速找到节点和执行初始化节点模型。
|
|
132
|
+
* 同时此方法还会找到所有的开始节点,方便后续执行时,从开始节点开始执行。
|
|
133
|
+
* @param graphData 流程图数据
|
|
134
|
+
*/
|
|
135
|
+
public load(graphData: Engine.GraphConfigData) {
|
|
136
|
+
const { nodes = [], edges = [] } = graphData
|
|
137
|
+
nodes.forEach((node) => {
|
|
138
|
+
if (this.nodeModelMap.has(node.type)) {
|
|
139
|
+
const nodeConfig: BaseNode.NodeConfig = {
|
|
140
|
+
id: node.id,
|
|
141
|
+
type: node.type,
|
|
142
|
+
properties: node.properties,
|
|
143
|
+
incoming: [],
|
|
144
|
+
outgoing: [],
|
|
145
|
+
}
|
|
146
|
+
this.nodeConfigMap.set(node.id, nodeConfig)
|
|
147
|
+
if (node.type === this.startNodeType) {
|
|
148
|
+
this.startNodes.push(nodeConfig)
|
|
149
|
+
}
|
|
150
|
+
} else {
|
|
151
|
+
console.warn(`未识别的节点类型:${node.type}`)
|
|
152
|
+
}
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
edges.forEach((edge) => {
|
|
156
|
+
const sourceNode = this.nodeConfigMap.get(edge.sourceNodeId)
|
|
157
|
+
const targetNode = this.nodeConfigMap.get(edge.targetNodeId)
|
|
158
|
+
if (sourceNode) {
|
|
159
|
+
sourceNode.outgoing.push({
|
|
160
|
+
id: edge.id,
|
|
161
|
+
properties: edge.properties,
|
|
162
|
+
target: edge.targetNodeId,
|
|
163
|
+
})
|
|
164
|
+
}
|
|
165
|
+
if (targetNode && targetNode.type !== this.startNodeType) {
|
|
166
|
+
targetNode.incoming.push({
|
|
167
|
+
id: edge.id,
|
|
168
|
+
properties: edge.properties,
|
|
169
|
+
source: edge.sourceNodeId,
|
|
170
|
+
})
|
|
171
|
+
}
|
|
172
|
+
})
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* 从待执行队列中取出需要执行的内容。
|
|
177
|
+
* 会依次判断是否有 actionId、nodeId、executionId。
|
|
178
|
+
* 若存在 actionId,那么表示恢复执行
|
|
179
|
+
* 若存在 nodeId,那么表示从指定节点开始执行
|
|
180
|
+
* 若都不存在,那么新建一个 executionId,从开始节点开始执行
|
|
181
|
+
* @private
|
|
182
|
+
*/
|
|
183
|
+
private createExecution(execParam: Partial<FlowModel.ExecParam>) {
|
|
184
|
+
this.executeList.push(execParam)
|
|
185
|
+
|
|
186
|
+
// 如果有 actionId,则表示恢复执行
|
|
187
|
+
// TODO: 待测试,确认该流程
|
|
188
|
+
if (execParam.actionId && execParam.nodeId && execParam.executionId) {
|
|
189
|
+
this.scheduler.resume({
|
|
190
|
+
executionId: execParam.executionId,
|
|
191
|
+
actionId: execParam.actionId,
|
|
192
|
+
nodeId: execParam.nodeId,
|
|
193
|
+
data: execParam.data,
|
|
194
|
+
})
|
|
195
|
+
return
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// 否则,判断 executionId 是否存在,使用 executionId 或创建新的 execution,从开始节点开始执行
|
|
199
|
+
// const executionId = execParam?.executionId || createExecId()
|
|
200
|
+
const executionId = createExecId()
|
|
201
|
+
execParam.executionId = executionId
|
|
202
|
+
|
|
203
|
+
// 当指定了具体需要执行的节点时,执行下面方法
|
|
204
|
+
if (execParam?.nodeId) {
|
|
205
|
+
const nodeConfig = this.nodeConfigMap.get(execParam.nodeId)
|
|
206
|
+
if (!nodeConfig) {
|
|
207
|
+
execParam?.onError?.(
|
|
208
|
+
new Error(
|
|
209
|
+
`${getErrorMsg(ErrorCode.NONE_NODE_ID)}(${execParam.nodeId})`,
|
|
210
|
+
),
|
|
211
|
+
)
|
|
212
|
+
return
|
|
213
|
+
}
|
|
214
|
+
// 当指定了开始节点,且该节点存在,则直接以这个节点开始执行
|
|
215
|
+
this.startNodes = [nodeConfig]
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
this.startNodes.forEach((startNode) => {
|
|
219
|
+
this.scheduler.addAction({
|
|
220
|
+
executionId,
|
|
221
|
+
nodeId: startNode.id,
|
|
222
|
+
})
|
|
223
|
+
})
|
|
224
|
+
// 所有的开始节点都执行
|
|
225
|
+
this.scheduler.run({
|
|
226
|
+
executionId,
|
|
227
|
+
})
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* 执行流程,每次执行都会生成一个唯一的 executionId,用于区分不同的执行。
|
|
232
|
+
* 同一次执行,这次执行内部的节点执行顺序为并行。内部并行是为了避免异步节点阻塞其他节点的执行
|
|
233
|
+
* 多次执行,多次执行之间为串行,这里选择串行的原因是避免多次执行之间的数据冲突。
|
|
234
|
+
* 例如:
|
|
235
|
+
* 一个流程存在两个开始节点,A 和 B,A 和 B 的下一个节点都是 C,C 的下两个节点是 D 和 E
|
|
236
|
+
* 外部分别触发了 A 和 B 的执行,那么 A 和 B 的执行是串行(即 A 执行完再执行 B),但是 D 和 E 的执行是并行的。
|
|
237
|
+
* 如果希望 A 和 B 的执行时并行的,就不能使用同一个流程模型执行,应该初始化两个。
|
|
238
|
+
* 下面直接使用调度器的队列
|
|
239
|
+
* @param params
|
|
240
|
+
*/
|
|
241
|
+
public async execute(params: Partial<FlowModel.ExecParam>) {
|
|
242
|
+
this.createExecution(params)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
public async resume(params: Partial<FlowModel.ExecParam>) {
|
|
246
|
+
this.createExecution(params)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* 创建节点实例,每个节点实例都会有一个唯一的 actionId
|
|
251
|
+
* 通过 executionId, nodeId, actionId 可以唯一确定一个节点的某一次执行
|
|
252
|
+
* @param nodeId
|
|
253
|
+
* @returns 节点实例
|
|
254
|
+
*/
|
|
255
|
+
// TODO: 确认下面这种场景,类型如何定义
|
|
256
|
+
public createAction(nodeId: Engine.Key) {
|
|
257
|
+
const nodeConfig = this.nodeConfigMap.get(nodeId)
|
|
258
|
+
if (nodeConfig) {
|
|
259
|
+
const NodeModel = this.nodeModelMap.get(nodeConfig.type)
|
|
260
|
+
if (!NodeModel) {
|
|
261
|
+
throw new Error('该 NodeModel 不存在,抛出异常')
|
|
262
|
+
}
|
|
263
|
+
return new NodeModel({
|
|
264
|
+
nodeConfig,
|
|
265
|
+
globalData: this.globalData,
|
|
266
|
+
context: this.context,
|
|
267
|
+
})
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
public setStartNodeType(type: string) {
|
|
272
|
+
this.startNodeType = type
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
public updateGlobalData(data: Record<string, unknown>) {
|
|
276
|
+
// TODO: 数据的合并,是否考虑子项的合并(默认值的替换)
|
|
277
|
+
this.globalData = {
|
|
278
|
+
...this.globalData,
|
|
279
|
+
...data,
|
|
280
|
+
}
|
|
281
|
+
return this.globalData
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* 在执行完成后,通知外部此次之行完成
|
|
286
|
+
* 如果还存在待执行的任务,那么继续执行
|
|
287
|
+
* @param result
|
|
288
|
+
* @private
|
|
289
|
+
*/
|
|
290
|
+
private onExecuteFinished(result) {
|
|
291
|
+
const index = this.executeList.findIndex(
|
|
292
|
+
(i) => i.executionId === result.executionId,
|
|
293
|
+
)
|
|
294
|
+
if (index > -1) {
|
|
295
|
+
const { callback } = this.executeList[index]
|
|
296
|
+
this.executeList.splice(index, 1)
|
|
297
|
+
callback?.(result)
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export namespace FlowModel {
|
|
303
|
+
export type FlowResult =
|
|
304
|
+
| ({
|
|
305
|
+
result?: Record<string, unknown>
|
|
306
|
+
} & Engine.ActionParam)
|
|
307
|
+
| Engine.NextActionParam
|
|
308
|
+
|
|
309
|
+
export type ActionParam = Scheduler.ActionParam
|
|
310
|
+
|
|
311
|
+
export type ExecParam = {
|
|
312
|
+
callback?: (result: Engine.NextActionParam) => void
|
|
313
|
+
onError?: (error: Error) => void
|
|
314
|
+
} & ActionParam
|
|
315
|
+
|
|
316
|
+
export interface IFlowModelProps {
|
|
317
|
+
nodeModelMap: Map<string, BaseNode.NodeConstructor>
|
|
318
|
+
recorder?: Recorder
|
|
319
|
+
context?: Record<string, unknown>
|
|
320
|
+
globalData?: Record<string, unknown>
|
|
321
|
+
startNodeType?: string
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
export default FlowModel
|