@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.
Files changed (153) hide show
  1. package/LICENSE +201 -0
  2. package/esm/actions/flow_nodes.d.ts +3 -0
  3. package/esm/actions/flow_nodes.js +139 -0
  4. package/esm/actions/flow_nodes.js.map +1 -0
  5. package/esm/actions/index.d.ts +1 -0
  6. package/esm/actions/index.js +8 -0
  7. package/esm/actions/index.js.map +1 -0
  8. package/esm/calculators/index.d.ts +38 -0
  9. package/esm/calculators/index.js +128 -0
  10. package/esm/calculators/index.js.map +1 -0
  11. package/esm/collections/executions.d.ts +3 -0
  12. package/esm/collections/executions.js +38 -0
  13. package/esm/collections/executions.js.map +1 -0
  14. package/esm/collections/flow_nodes.d.ts +3 -0
  15. package/esm/collections/flow_nodes.js +72 -0
  16. package/esm/collections/flow_nodes.js.map +1 -0
  17. package/esm/collections/jobs.d.ts +3 -0
  18. package/esm/collections/jobs.js +47 -0
  19. package/esm/collections/jobs.js.map +1 -0
  20. package/esm/collections/workflows.d.ts +3 -0
  21. package/esm/collections/workflows.js +63 -0
  22. package/esm/collections/workflows.js.map +1 -0
  23. package/esm/constants.d.ts +17 -0
  24. package/esm/constants.js +18 -0
  25. package/esm/constants.js.map +1 -0
  26. package/esm/index.d.ts +5 -0
  27. package/esm/index.js +6 -0
  28. package/esm/index.js.map +1 -0
  29. package/esm/instructions/calculation.d.ts +8 -0
  30. package/esm/instructions/calculation.js +55 -0
  31. package/esm/instructions/calculation.js.map +1 -0
  32. package/esm/instructions/condition.d.ts +5 -0
  33. package/esm/instructions/condition.js +99 -0
  34. package/esm/instructions/condition.js.map +1 -0
  35. package/esm/instructions/create.d.ts +8 -0
  36. package/esm/instructions/create.js +25 -0
  37. package/esm/instructions/create.js.map +1 -0
  38. package/esm/instructions/destroy.d.ts +8 -0
  39. package/esm/instructions/destroy.js +25 -0
  40. package/esm/instructions/destroy.js.map +1 -0
  41. package/esm/instructions/index.d.ts +15 -0
  42. package/esm/instructions/index.js +20 -0
  43. package/esm/instructions/index.js.map +1 -0
  44. package/esm/instructions/parallel.d.ts +13 -0
  45. package/esm/instructions/parallel.js +88 -0
  46. package/esm/instructions/parallel.js.map +1 -0
  47. package/esm/instructions/prompt.d.ts +7 -0
  48. package/esm/instructions/prompt.js +13 -0
  49. package/esm/instructions/prompt.js.map +1 -0
  50. package/esm/instructions/query.d.ts +8 -0
  51. package/esm/instructions/query.js +25 -0
  52. package/esm/instructions/query.js.map +1 -0
  53. package/esm/instructions/update.d.ts +8 -0
  54. package/esm/instructions/update.js +25 -0
  55. package/esm/instructions/update.js.map +1 -0
  56. package/esm/models/Execution.d.ts +50 -0
  57. package/esm/models/Execution.js +250 -0
  58. package/esm/models/Execution.js.map +1 -0
  59. package/esm/models/FlowNode.d.ts +17 -0
  60. package/esm/models/FlowNode.js +4 -0
  61. package/esm/models/FlowNode.js.map +1 -0
  62. package/esm/models/Job.d.ts +15 -0
  63. package/esm/models/Job.js +4 -0
  64. package/esm/models/Job.js.map +1 -0
  65. package/esm/models/Workflow.d.ts +27 -0
  66. package/esm/models/Workflow.js +72 -0
  67. package/esm/models/Workflow.js.map +1 -0
  68. package/esm/server.d.ts +5 -0
  69. package/esm/server.js +62 -0
  70. package/esm/server.js.map +1 -0
  71. package/esm/triggers/index.d.ts +9 -0
  72. package/esm/triggers/index.js +6 -0
  73. package/esm/triggers/index.js.map +1 -0
  74. package/esm/triggers/model.d.ts +12 -0
  75. package/esm/triggers/model.js +47 -0
  76. package/esm/triggers/model.js.map +1 -0
  77. package/lib/actions/flow_nodes.d.ts +3 -0
  78. package/lib/actions/flow_nodes.js +163 -0
  79. package/lib/actions/flow_nodes.js.map +1 -0
  80. package/lib/actions/index.d.ts +1 -0
  81. package/lib/actions/index.js +30 -0
  82. package/lib/actions/index.js.map +1 -0
  83. package/lib/calculators/index.d.ts +38 -0
  84. package/lib/calculators/index.js +132 -0
  85. package/lib/calculators/index.js.map +1 -0
  86. package/lib/collections/executions.d.ts +3 -0
  87. package/lib/collections/executions.js +40 -0
  88. package/lib/collections/executions.js.map +1 -0
  89. package/lib/collections/flow_nodes.d.ts +3 -0
  90. package/lib/collections/flow_nodes.js +74 -0
  91. package/lib/collections/flow_nodes.js.map +1 -0
  92. package/lib/collections/jobs.d.ts +3 -0
  93. package/lib/collections/jobs.js +49 -0
  94. package/lib/collections/jobs.js.map +1 -0
  95. package/lib/collections/workflows.d.ts +3 -0
  96. package/lib/collections/workflows.js +65 -0
  97. package/lib/collections/workflows.js.map +1 -0
  98. package/lib/constants.d.ts +17 -0
  99. package/lib/constants.js +21 -0
  100. package/lib/constants.js.map +1 -0
  101. package/lib/index.d.ts +5 -0
  102. package/lib/index.js +23 -0
  103. package/lib/index.js.map +1 -0
  104. package/lib/instructions/calculation.d.ts +8 -0
  105. package/lib/instructions/calculation.js +57 -0
  106. package/lib/instructions/calculation.js.map +1 -0
  107. package/lib/instructions/condition.d.ts +5 -0
  108. package/lib/instructions/condition.js +120 -0
  109. package/lib/instructions/condition.js.map +1 -0
  110. package/lib/instructions/create.d.ts +8 -0
  111. package/lib/instructions/create.js +27 -0
  112. package/lib/instructions/create.js.map +1 -0
  113. package/lib/instructions/destroy.d.ts +8 -0
  114. package/lib/instructions/destroy.js +27 -0
  115. package/lib/instructions/destroy.js.map +1 -0
  116. package/lib/instructions/index.d.ts +15 -0
  117. package/lib/instructions/index.js +26 -0
  118. package/lib/instructions/index.js.map +1 -0
  119. package/lib/instructions/parallel.d.ts +13 -0
  120. package/lib/instructions/parallel.js +91 -0
  121. package/lib/instructions/parallel.js.map +1 -0
  122. package/lib/instructions/prompt.d.ts +7 -0
  123. package/lib/instructions/prompt.js +15 -0
  124. package/lib/instructions/prompt.js.map +1 -0
  125. package/lib/instructions/query.d.ts +8 -0
  126. package/lib/instructions/query.js +27 -0
  127. package/lib/instructions/query.js.map +1 -0
  128. package/lib/instructions/update.d.ts +8 -0
  129. package/lib/instructions/update.js +27 -0
  130. package/lib/instructions/update.js.map +1 -0
  131. package/lib/models/Execution.d.ts +50 -0
  132. package/lib/models/Execution.js +256 -0
  133. package/lib/models/Execution.js.map +1 -0
  134. package/lib/models/FlowNode.d.ts +17 -0
  135. package/lib/models/FlowNode.js +7 -0
  136. package/lib/models/FlowNode.js.map +1 -0
  137. package/lib/models/Job.d.ts +15 -0
  138. package/lib/models/Job.js +7 -0
  139. package/lib/models/Job.js.map +1 -0
  140. package/lib/models/Workflow.d.ts +27 -0
  141. package/lib/models/Workflow.js +78 -0
  142. package/lib/models/Workflow.js.map +1 -0
  143. package/lib/server.d.ts +5 -0
  144. package/lib/server.js +68 -0
  145. package/lib/server.js.map +1 -0
  146. package/lib/triggers/index.d.ts +9 -0
  147. package/lib/triggers/index.js +12 -0
  148. package/lib/triggers/index.js.map +1 -0
  149. package/lib/triggers/model.d.ts +12 -0
  150. package/lib/triggers/model.js +49 -0
  151. package/lib/triggers/model.js.map +1 -0
  152. package/package.json +28 -0
  153. package/tsconfig.build.json +9 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/instructions/create.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,4CAA0C;AAG1C,kBAAe;IACP,GAAG,CAAsB,KAAK,EAAE,SAAS;;YAC7C,MAAM,EACJ,UAAU,EACV,MAAM,GAAG,EAAE,EACZ,GAAG,IAAI,CAAC,MAAM,CAAC;YAEhB,MAAM,IAAI,GAA0B,IAAI,CAAC,WAAY,CAAC,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;YACzF,MAAM,OAAO,GAAG,SAAS,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;YACjD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,iCAC3B,OAAO,KACV,WAAW,EAAE,SAAS,CAAC,WAAW,IAClC,CAAC;YAEH,OAAO;gBACL,MAAM;gBACN,MAAM,EAAE,sBAAU,CAAC,QAAQ;aAC5B,CAAC;QACJ,CAAC;KAAA;CACF,CAAA","sourcesContent":["import { JOB_STATUS } from \"../constants\";\nimport FlowNodeModel from \"../models/FlowNode\";\n\nexport default {\n async run(this: FlowNodeModel, input, execution) {\n const {\n collection,\n params = {}\n } = this.config;\n\n const repo = (<typeof FlowNodeModel>this.constructor).database.getRepository(collection);\n const options = execution.getParsedValue(params);\n const result = await repo.create({\n ...options,\n transaction: execution.transaction\n });\n\n return {\n result,\n status: JOB_STATUS.RESOLVED\n };\n }\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import FlowNodeModel from "../models/FlowNode";
2
+ declare const _default: {
3
+ run(this: FlowNodeModel, input: any, execution: any): Promise<{
4
+ result: any;
5
+ status: number;
6
+ }>;
7
+ };
8
+ export default _default;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const constants_1 = require("../constants");
13
+ exports.default = {
14
+ run(input, execution) {
15
+ return __awaiter(this, void 0, void 0, function* () {
16
+ const { collection, params = {} } = this.config;
17
+ const repo = this.constructor.database.getRepository(collection);
18
+ const options = execution.getParsedValue(params);
19
+ const result = yield repo.destroy(Object.assign(Object.assign({}, options), { transaction: execution.transaction }));
20
+ return {
21
+ result,
22
+ status: constants_1.JOB_STATUS.RESOLVED
23
+ };
24
+ });
25
+ }
26
+ };
27
+ //# sourceMappingURL=destroy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"destroy.js","sourceRoot":"","sources":["../../src/instructions/destroy.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,4CAA0C;AAG1C,kBAAe;IACP,GAAG,CAAsB,KAAK,EAAE,SAAS;;YAC7C,MAAM,EACJ,UAAU,EACV,MAAM,GAAG,EAAE,EACZ,GAAG,IAAI,CAAC,MAAM,CAAC;YAEhB,MAAM,IAAI,GAA0B,IAAI,CAAC,WAAY,CAAC,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;YACzF,MAAM,OAAO,GAAG,SAAS,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;YACjD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,iCAC5B,OAAO,KACV,WAAW,EAAE,SAAS,CAAC,WAAW,IAClC,CAAC;YAEH,OAAO;gBACL,MAAM;gBACN,MAAM,EAAE,sBAAU,CAAC,QAAQ;aAC5B,CAAC;QACJ,CAAC;KAAA;CACF,CAAA","sourcesContent":["import { JOB_STATUS } from \"../constants\";\nimport FlowNodeModel from \"../models/FlowNode\";\n\nexport default {\n async run(this: FlowNodeModel, input, execution) {\n const {\n collection,\n params = {}\n } = this.config;\n\n const repo = (<typeof FlowNodeModel>this.constructor).database.getRepository(collection);\n const options = execution.getParsedValue(params);\n const result = await repo.destroy({\n ...options,\n transaction: execution.transaction\n });\n\n return {\n result,\n status: JOB_STATUS.RESOLVED\n };\n }\n}\n"]}
@@ -0,0 +1,15 @@
1
+ import { Registry } from '@nocobase/utils';
2
+ import ExecutionModel from '../models/Execution';
3
+ import FlowNodeModel from '../models/FlowNode';
4
+ export interface Job {
5
+ status: number;
6
+ result?: unknown;
7
+ [key: string]: unknown;
8
+ }
9
+ export declare type InstructionResult = Job | Promise<Job>;
10
+ export interface Instruction {
11
+ run(this: FlowNodeModel, input: any, execution: ExecutionModel): InstructionResult;
12
+ resume?(this: FlowNodeModel, input: any, execution: ExecutionModel): InstructionResult;
13
+ }
14
+ export declare const instructions: Registry<Instruction>;
15
+ export default instructions;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.instructions = void 0;
7
+ const utils_1 = require("@nocobase/utils");
8
+ const prompt_1 = __importDefault(require("./prompt"));
9
+ const calculation_1 = __importDefault(require("./calculation"));
10
+ const condition_1 = __importDefault(require("./condition"));
11
+ const parallel_1 = __importDefault(require("./parallel"));
12
+ const query_1 = __importDefault(require("./query"));
13
+ const create_1 = __importDefault(require("./create"));
14
+ const update_1 = __importDefault(require("./update"));
15
+ const destroy_1 = __importDefault(require("./destroy"));
16
+ exports.instructions = new utils_1.Registry();
17
+ exports.instructions.register('prompt', prompt_1.default);
18
+ exports.instructions.register('calculation', calculation_1.default);
19
+ exports.instructions.register('condition', condition_1.default);
20
+ exports.instructions.register('parallel', parallel_1.default);
21
+ exports.instructions.register('query', query_1.default);
22
+ exports.instructions.register('create', create_1.default);
23
+ exports.instructions.register('update', update_1.default);
24
+ exports.instructions.register('destroy', destroy_1.default);
25
+ exports.default = exports.instructions;
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/instructions/index.ts"],"names":[],"mappings":";;;;;;AAAA,2CAA2C;AAK3C,sDAA8B;AAC9B,gEAAwC;AACxC,4DAAoC;AACpC,0DAAkC;AAClC,oDAA4B;AAC5B,sDAA8B;AAC9B,sDAA8B;AAC9B,wDAAgC;AA+BnB,QAAA,YAAY,GAAG,IAAI,gBAAQ,EAAe,CAAC;AAExD,oBAAY,CAAC,QAAQ,CAAC,QAAQ,EAAE,gBAAM,CAAC,CAAC;AACxC,oBAAY,CAAC,QAAQ,CAAC,aAAa,EAAE,qBAAW,CAAC,CAAC;AAClD,oBAAY,CAAC,QAAQ,CAAC,WAAW,EAAE,mBAAS,CAAC,CAAC;AAC9C,oBAAY,CAAC,QAAQ,CAAC,UAAU,EAAE,kBAAQ,CAAC,CAAC;AAC5C,oBAAY,CAAC,QAAQ,CAAC,OAAO,EAAE,eAAK,CAAC,CAAC;AACtC,oBAAY,CAAC,QAAQ,CAAC,QAAQ,EAAE,gBAAM,CAAC,CAAC;AACxC,oBAAY,CAAC,QAAQ,CAAC,QAAQ,EAAE,gBAAM,CAAC,CAAC;AACxC,oBAAY,CAAC,QAAQ,CAAC,SAAS,EAAE,iBAAO,CAAC,CAAC;AAE1C,kBAAe,oBAAY,CAAC","sourcesContent":["import { Registry } from '@nocobase/utils';\n\nimport ExecutionModel from '../models/Execution';\nimport FlowNodeModel from '../models/FlowNode';\n\nimport prompt from './prompt';\nimport calculation from './calculation';\nimport condition from './condition';\nimport parallel from './parallel';\nimport query from './query';\nimport create from './create';\nimport update from './update';\nimport destroy from './destroy';\n\nexport interface Job {\n status: number;\n result?: unknown;\n [key: string]: unknown;\n}\n\nexport type InstructionResult = Job | Promise<Job>;\n\n// what should a instruction do?\n// - base on input and context, do any calculations or system call (io), and produce a result or pending.\nexport interface Instruction {\n run(\n this: FlowNodeModel,\n // what should input to be?\n // - just use previously output result for convenience?\n input: any,\n // what should context to be?\n // - could be the workflow execution object (containing context data)\n execution: ExecutionModel\n ): InstructionResult;\n\n // for start node in main flow (or branch) to resume when manual sub branch triggered\n resume?(\n this: FlowNodeModel,\n input: any,\n execution: ExecutionModel\n ): InstructionResult\n}\n\nexport const instructions = new Registry<Instruction>();\n\ninstructions.register('prompt', prompt);\ninstructions.register('calculation', calculation);\ninstructions.register('condition', condition);\ninstructions.register('parallel', parallel);\ninstructions.register('query', query);\ninstructions.register('create', create);\ninstructions.register('update', update);\ninstructions.register('destroy', destroy);\n\nexport default instructions;\n"]}
@@ -0,0 +1,13 @@
1
+ import ExecutionModel from "../models/Execution";
2
+ import FlowNodeModel from "../models/FlowNode";
3
+ import JobModel from "../models/Job";
4
+ export declare const PARALLEL_MODE: {
5
+ readonly ALL: "all";
6
+ readonly ANY: "any";
7
+ readonly RACE: "race";
8
+ };
9
+ declare const _default: {
10
+ run(this: FlowNodeModel, prevJob: JobModel, execution: ExecutionModel): Promise<any>;
11
+ resume(this: any, branchJob: any, execution: ExecutionModel): Promise<any>;
12
+ };
13
+ export default _default;
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.PARALLEL_MODE = void 0;
13
+ const constants_1 = require("../constants");
14
+ exports.PARALLEL_MODE = {
15
+ ALL: 'all',
16
+ ANY: 'any',
17
+ RACE: 'race'
18
+ };
19
+ const StatusGetters = {
20
+ [exports.PARALLEL_MODE.ALL](result) {
21
+ if (result.some(j => j && j.status === constants_1.JOB_STATUS.REJECTED)) {
22
+ return constants_1.JOB_STATUS.REJECTED;
23
+ }
24
+ if (result.every(j => j && j.status === constants_1.JOB_STATUS.RESOLVED)) {
25
+ return constants_1.JOB_STATUS.RESOLVED;
26
+ }
27
+ return constants_1.JOB_STATUS.PENDING;
28
+ },
29
+ [exports.PARALLEL_MODE.ANY](result) {
30
+ return result.some(j => j && j.status === constants_1.JOB_STATUS.RESOLVED)
31
+ ? constants_1.JOB_STATUS.RESOLVED
32
+ : (result.some(j => j && j.status === constants_1.JOB_STATUS.PENDING)
33
+ ? constants_1.JOB_STATUS.PENDING
34
+ : constants_1.JOB_STATUS.REJECTED);
35
+ },
36
+ [exports.PARALLEL_MODE.RACE](result) {
37
+ return result.some(j => j && j.status === constants_1.JOB_STATUS.RESOLVED)
38
+ ? constants_1.JOB_STATUS.RESOLVED
39
+ : (result.some(j => j && j.status === constants_1.JOB_STATUS.REJECTED)
40
+ ? constants_1.JOB_STATUS.REJECTED
41
+ : constants_1.JOB_STATUS.PENDING);
42
+ }
43
+ };
44
+ exports.default = {
45
+ run(prevJob, execution) {
46
+ var _a;
47
+ return __awaiter(this, void 0, void 0, function* () {
48
+ const branches = execution.nodes
49
+ .filter(item => item.upstream === this && item.branchIndex !== null)
50
+ .sort((a, b) => a.branchIndex - b.branchIndex);
51
+ const job = yield execution.saveJob({
52
+ status: constants_1.JOB_STATUS.PENDING,
53
+ result: Array(branches.length).fill(null),
54
+ nodeId: this.id,
55
+ upstreamId: (_a = prevJob === null || prevJob === void 0 ? void 0 : prevJob.id) !== null && _a !== void 0 ? _a : null
56
+ });
57
+ // NOTE:
58
+ // use `reduce` but not `Promise.all` here to avoid racing manupulating db.
59
+ // for users, this is almost equivalent to `Promise.all`,
60
+ // because of the delay is not significant sensible.
61
+ // another better aspect of this is, it could handle sequenced branches in future.
62
+ yield branches.reduce((promise, branch) => promise.then(() => execution.run(branch, job)), Promise.resolve());
63
+ return execution.end(this, job);
64
+ });
65
+ },
66
+ resume(branchJob, execution) {
67
+ return __awaiter(this, void 0, void 0, function* () {
68
+ const job = execution.findBranchParentJob(branchJob, this);
69
+ const { result, status } = job;
70
+ // if parallel has been done (resolved / rejected), do not care newly executed branch jobs.
71
+ if (status !== constants_1.JOB_STATUS.PENDING) {
72
+ return null;
73
+ }
74
+ // find the index of the node which start the branch
75
+ const jobNode = execution.nodesMap.get(branchJob.nodeId);
76
+ const { branchIndex } = execution.findBranchStartNode(jobNode);
77
+ const { mode = exports.PARALLEL_MODE.ALL } = this.config || {};
78
+ const newResult = [...result.slice(0, branchIndex), branchJob.get(), ...result.slice(branchIndex + 1)];
79
+ job.set({
80
+ result: newResult,
81
+ status: StatusGetters[mode](newResult)
82
+ });
83
+ if (job.status === constants_1.JOB_STATUS.PENDING) {
84
+ yield job.save({ transaction: execution.transaction });
85
+ return execution.end(this, job);
86
+ }
87
+ return job;
88
+ });
89
+ }
90
+ };
91
+ //# sourceMappingURL=parallel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parallel.js","sourceRoot":"","sources":["../../src/instructions/parallel.ts"],"names":[],"mappings":"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","sourcesContent":["import { JOB_STATUS } from \"../constants\";\nimport ExecutionModel from \"../models/Execution\";\nimport FlowNodeModel from \"../models/FlowNode\";\nimport JobModel from \"../models/Job\";\n\nexport const PARALLEL_MODE = {\n ALL: 'all',\n ANY: 'any',\n RACE: 'race'\n} as const;\n\nconst StatusGetters = {\n [PARALLEL_MODE.ALL](result) {\n if (result.some(j => j && j.status === JOB_STATUS.REJECTED)) {\n return JOB_STATUS.REJECTED;\n }\n if (result.every(j => j && j.status === JOB_STATUS.RESOLVED)) {\n return JOB_STATUS.RESOLVED;\n }\n return JOB_STATUS.PENDING;\n },\n [PARALLEL_MODE.ANY](result) {\n return result.some(j => j && j.status === JOB_STATUS.RESOLVED)\n ? JOB_STATUS.RESOLVED\n : (\n result.some(j => j && j.status === JOB_STATUS.PENDING)\n ? JOB_STATUS.PENDING\n : JOB_STATUS.REJECTED\n )\n },\n [PARALLEL_MODE.RACE](result) {\n return result.some(j => j && j.status === JOB_STATUS.RESOLVED)\n ? JOB_STATUS.RESOLVED\n : (\n result.some(j => j && j.status === JOB_STATUS.REJECTED)\n ? JOB_STATUS.REJECTED\n : JOB_STATUS.PENDING\n )\n }\n};\n\nexport default {\n async run(this: FlowNodeModel, prevJob: JobModel, execution: ExecutionModel) {\n const branches = execution.nodes\n .filter(item => item.upstream === this && item.branchIndex !== null)\n .sort((a, b) => a.branchIndex - b.branchIndex);\n\n const job = await execution.saveJob({\n status: JOB_STATUS.PENDING,\n result: Array(branches.length).fill(null),\n nodeId: this.id,\n upstreamId: prevJob?.id ?? null\n });\n\n // NOTE:\n // use `reduce` but not `Promise.all` here to avoid racing manupulating db.\n // for users, this is almost equivalent to `Promise.all`,\n // because of the delay is not significant sensible.\n // another better aspect of this is, it could handle sequenced branches in future.\n await branches.reduce((promise: Promise<any>, branch) => promise.then(() => execution.run(branch, job)), Promise.resolve());\n\n return execution.end(this, job);\n },\n\n async resume(this, branchJob, execution: ExecutionModel) {\n const job = execution.findBranchParentJob(branchJob, this);\n\n const { result, status } = job;\n // if parallel has been done (resolved / rejected), do not care newly executed branch jobs.\n if (status !== JOB_STATUS.PENDING) {\n return null;\n }\n\n // find the index of the node which start the branch\n const jobNode = execution.nodesMap.get(branchJob.nodeId);\n const { branchIndex } = execution.findBranchStartNode(jobNode);\n const { mode = PARALLEL_MODE.ALL } = this.config || {};\n\n const newResult = [...result.slice(0, branchIndex), branchJob.get(), ...result.slice(branchIndex + 1)];\n job.set({\n result: newResult,\n status: StatusGetters[mode](newResult)\n });\n\n if (job.status === JOB_STATUS.PENDING) {\n await job.save({ transaction: execution.transaction });\n return execution.end(this, job);\n }\n\n return job;\n }\n};\n"]}
@@ -0,0 +1,7 @@
1
+ declare const _default: {
2
+ run(this: any, input: any, execution: any): {
3
+ status: number;
4
+ };
5
+ resume(this: any, job: any, execution: any): any;
6
+ };
7
+ export default _default;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const constants_1 = require("../constants");
4
+ exports.default = {
5
+ run(input, execution) {
6
+ return {
7
+ status: constants_1.JOB_STATUS.PENDING
8
+ };
9
+ },
10
+ resume(job, execution) {
11
+ job.set('status', constants_1.JOB_STATUS.RESOLVED);
12
+ return job;
13
+ }
14
+ };
15
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/instructions/prompt.ts"],"names":[],"mappings":";;AAAA,4CAA0C;AAE1C,kBAAe;IACb,GAAG,CAAO,KAAK,EAAE,SAAS;QACxB,OAAO;YACL,MAAM,EAAE,sBAAU,CAAC,OAAO;SAC3B,CAAC;IACJ,CAAC;IAED,MAAM,CAAO,GAAG,EAAE,SAAS;QACzB,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,sBAAU,CAAC,QAAQ,CAAC,CAAC;QACvC,OAAO,GAAG,CAAC;IACb,CAAC;CACF,CAAC","sourcesContent":["import { JOB_STATUS } from \"../constants\";\n\nexport default {\n run(this, input, execution) {\n return {\n status: JOB_STATUS.PENDING\n };\n },\n\n resume(this, job, execution) {\n job.set('status', JOB_STATUS.RESOLVED);\n return job;\n }\n};\n"]}
@@ -0,0 +1,8 @@
1
+ import FlowNodeModel from "../models/FlowNode";
2
+ declare const _default: {
3
+ run(this: FlowNodeModel, input: any, execution: any): Promise<{
4
+ result: any;
5
+ status: number;
6
+ }>;
7
+ };
8
+ export default _default;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const constants_1 = require("../constants");
13
+ exports.default = {
14
+ run(input, execution) {
15
+ return __awaiter(this, void 0, void 0, function* () {
16
+ const { collection, multiple, params = {} } = this.config;
17
+ const repo = this.constructor.database.getRepository(collection);
18
+ const options = execution.getParsedValue(params);
19
+ const result = yield (multiple ? repo.find : repo.findOne).call(repo, Object.assign(Object.assign({}, options), { transaction: execution.transaction }));
20
+ return {
21
+ result,
22
+ status: constants_1.JOB_STATUS.RESOLVED
23
+ };
24
+ });
25
+ }
26
+ };
27
+ //# sourceMappingURL=query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/instructions/query.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,4CAA0C;AAG1C,kBAAe;IACP,GAAG,CAAsB,KAAK,EAAE,SAAS;;YAC7C,MAAM,EACJ,UAAU,EACV,QAAQ,EACR,MAAM,GAAG,EAAE,EACZ,GAAG,IAAI,CAAC,MAAM,CAAC;YAEhB,MAAM,IAAI,GAA0B,IAAI,CAAC,WAAY,CAAC,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;YACzF,MAAM,OAAO,GAAG,SAAS,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;YACjD,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,kCAC/D,OAAO,KACV,WAAW,EAAE,SAAS,CAAC,WAAW,IAClC,CAAC;YAEH,OAAO;gBACL,MAAM;gBACN,MAAM,EAAE,sBAAU,CAAC,QAAQ;aAC5B,CAAC;QACJ,CAAC;KAAA;CACF,CAAC","sourcesContent":["import { JOB_STATUS } from \"../constants\";\nimport FlowNodeModel from \"../models/FlowNode\";\n\nexport default {\n async run(this: FlowNodeModel, input, execution) {\n const {\n collection,\n multiple,\n params = {}\n } = this.config;\n\n const repo = (<typeof FlowNodeModel>this.constructor).database.getRepository(collection);\n const options = execution.getParsedValue(params);\n const result = await (multiple ? repo.find : repo.findOne).call(repo, {\n ...options,\n transaction: execution.transaction\n });\n\n return {\n result,\n status: JOB_STATUS.RESOLVED\n };\n }\n};\n"]}
@@ -0,0 +1,8 @@
1
+ import FlowNodeModel from "../models/FlowNode";
2
+ declare const _default: {
3
+ run(this: FlowNodeModel, input: any, execution: any): Promise<{
4
+ result: import("@nocobase/database").Model<any, any> | import("@nocobase/database").Model<any, any>[];
5
+ status: number;
6
+ }>;
7
+ };
8
+ export default _default;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const constants_1 = require("../constants");
13
+ exports.default = {
14
+ run(input, execution) {
15
+ return __awaiter(this, void 0, void 0, function* () {
16
+ const { collection, multiple = false, params = {} } = this.config;
17
+ const repo = this.constructor.database.getRepository(collection);
18
+ const options = execution.getParsedValue(params);
19
+ const result = yield repo.update(Object.assign(Object.assign({}, options), { transaction: execution.transaction }));
20
+ return {
21
+ result: multiple ? result : (result[0] || null),
22
+ status: constants_1.JOB_STATUS.RESOLVED
23
+ };
24
+ });
25
+ }
26
+ };
27
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/instructions/update.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,4CAA0C;AAG1C,kBAAe;IACP,GAAG,CAAsB,KAAK,EAAE,SAAS;;YAC7C,MAAM,EACJ,UAAU,EACV,QAAQ,GAAG,KAAK,EAChB,MAAM,GAAG,EAAE,EACZ,GAAG,IAAI,CAAC,MAAM,CAAC;YAEhB,MAAM,IAAI,GAA0B,IAAI,CAAC,WAAY,CAAC,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;YACzF,MAAM,OAAO,GAAG,SAAS,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;YACjD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,iCAC3B,OAAO,KACV,WAAW,EAAE,SAAS,CAAC,WAAW,IAClC,CAAC;YAEH,OAAO;gBACL,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;gBAC/C,MAAM,EAAE,sBAAU,CAAC,QAAQ;aAC5B,CAAC;QACJ,CAAC;KAAA;CACF,CAAA","sourcesContent":["import { JOB_STATUS } from \"../constants\";\nimport FlowNodeModel from \"../models/FlowNode\";\n\nexport default {\n async run(this: FlowNodeModel, input, execution) {\n const {\n collection,\n multiple = false,\n params = {}\n } = this.config;\n\n const repo = (<typeof FlowNodeModel>this.constructor).database.getRepository(collection);\n const options = execution.getParsedValue(params);\n const result = await repo.update({\n ...options,\n transaction: execution.transaction\n });\n\n return {\n result: multiple ? result : (result[0] || null),\n status: JOB_STATUS.RESOLVED\n };\n }\n}\n"]}
@@ -0,0 +1,50 @@
1
+ import { Database, Model } from '@nocobase/database';
2
+ import { BelongsToGetAssociationMixin, HasManyGetAssociationsMixin, Transaction } from 'sequelize';
3
+ import WorkflowModel from './Workflow';
4
+ import FlowNodeModel from './FlowNode';
5
+ import JobModel from './Job';
6
+ export interface ExecutionOptions {
7
+ transaction?: Transaction;
8
+ }
9
+ export default class ExecutionModel extends Model {
10
+ static readonly database: Database;
11
+ id: number;
12
+ title: string;
13
+ context: any;
14
+ status: number;
15
+ useTransaction: boolean;
16
+ createdAt: Date;
17
+ updatedAt: Date;
18
+ workflow?: WorkflowModel;
19
+ getWorkflow: BelongsToGetAssociationMixin<WorkflowModel>;
20
+ jobs?: JobModel[];
21
+ getJobs: HasManyGetAssociationsMixin<JobModel>;
22
+ options: ExecutionOptions;
23
+ transaction: Transaction;
24
+ nodes: Array<FlowNodeModel>;
25
+ nodesMap: Map<number, FlowNodeModel>;
26
+ jobsMap: Map<number, JobModel>;
27
+ jobsMapByNodeId: {
28
+ [key: number]: any;
29
+ };
30
+ static StatusMap: {
31
+ [x: number]: number;
32
+ };
33
+ makeNodes(nodes?: any[]): void;
34
+ makeJobs(jobs: Array<JobModel>): void;
35
+ getTransaction(): Transaction | Promise<Transaction>;
36
+ prepare(options: any, commit?: boolean): Promise<void>;
37
+ start(options: ExecutionOptions): Promise<void>;
38
+ resume(job: JobModel, options: ExecutionOptions): Promise<void>;
39
+ private commit;
40
+ private exec;
41
+ run(node: any, input?: any): any;
42
+ end(node: any, job: any): any;
43
+ recall(node: any, job: any): any;
44
+ exit(job: JobModel | null): Promise<any>;
45
+ saveJob(payload: any): Promise<JobModel>;
46
+ findBranchStartNode(node: FlowNodeModel): FlowNodeModel | null;
47
+ findBranchParentNode(node: FlowNodeModel): FlowNodeModel | null;
48
+ findBranchParentJob(job: JobModel, node: FlowNodeModel): JobModel | null;
49
+ getParsedValue(value: any, node?: any): any;
50
+ }
@@ -0,0 +1,256 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const database_1 = require("@nocobase/database");
16
+ const json_templates_1 = __importDefault(require("json-templates"));
17
+ const constants_1 = require("../constants");
18
+ const instructions_1 = __importDefault(require("../instructions"));
19
+ const calculators_1 = __importDefault(require("../calculators"));
20
+ class ExecutionModel extends database_1.Model {
21
+ constructor() {
22
+ super(...arguments);
23
+ this.nodes = [];
24
+ this.nodesMap = new Map();
25
+ this.jobsMap = new Map();
26
+ this.jobsMapByNodeId = {};
27
+ }
28
+ // make dual linked nodes list then cache
29
+ makeNodes(nodes = []) {
30
+ this.nodes = nodes;
31
+ nodes.forEach((node) => {
32
+ this.nodesMap.set(node.id, node);
33
+ });
34
+ nodes.forEach((node) => {
35
+ if (node.upstreamId) {
36
+ node.upstream = this.nodesMap.get(node.upstreamId);
37
+ }
38
+ if (node.downstreamId) {
39
+ node.downstream = this.nodesMap.get(node.downstreamId);
40
+ }
41
+ });
42
+ }
43
+ makeJobs(jobs) {
44
+ jobs.forEach((job) => {
45
+ this.jobsMap.set(job.id, job);
46
+ // TODO: should consider cycle, and from previous job
47
+ this.jobsMapByNodeId[job.nodeId] = job.result;
48
+ });
49
+ }
50
+ getTransaction() {
51
+ const { sequelize } = this.constructor.database;
52
+ // @ts-ignore
53
+ if (!this.useTransaction) {
54
+ return undefined;
55
+ }
56
+ const { options } = this;
57
+ // @ts-ignore
58
+ return options.transaction && !options.transaction.finished
59
+ ? options.transaction
60
+ : sequelize.transaction();
61
+ }
62
+ prepare(options, commit = false) {
63
+ return __awaiter(this, void 0, void 0, function* () {
64
+ this.options = options || {};
65
+ // @ts-ignore
66
+ const transaction = yield this.getTransaction();
67
+ this.transaction = transaction;
68
+ if (!this.workflow) {
69
+ this.workflow = yield this.getWorkflow({ transaction });
70
+ }
71
+ const nodes = yield this.workflow.getNodes({ transaction });
72
+ this.makeNodes(nodes);
73
+ const jobs = yield this.getJobs({
74
+ order: [['id', 'ASC']],
75
+ transaction,
76
+ });
77
+ this.makeJobs(jobs);
78
+ if (commit) {
79
+ yield this.commit();
80
+ }
81
+ });
82
+ }
83
+ start(options) {
84
+ return __awaiter(this, void 0, void 0, function* () {
85
+ if (this.status !== constants_1.EXECUTION_STATUS.STARTED) {
86
+ throw new Error(`execution was ended with status ${this.status}`);
87
+ }
88
+ yield this.prepare(options);
89
+ if (this.nodes.length) {
90
+ const head = this.nodes.find(item => !item.upstream);
91
+ yield this.run(head, { result: this.context });
92
+ }
93
+ else {
94
+ yield this.exit(null);
95
+ }
96
+ yield this.commit();
97
+ });
98
+ }
99
+ resume(job, options) {
100
+ return __awaiter(this, void 0, void 0, function* () {
101
+ if (this.status !== constants_1.EXECUTION_STATUS.STARTED) {
102
+ throw new Error(`execution was ended with status ${this.status}`);
103
+ }
104
+ yield this.prepare(options);
105
+ const node = this.nodesMap.get(job.nodeId);
106
+ yield this.recall(node, job);
107
+ yield this.commit();
108
+ });
109
+ }
110
+ commit() {
111
+ return __awaiter(this, void 0, void 0, function* () {
112
+ // @ts-ignore
113
+ if (this.transaction && (!this.options.transaction || this.options.transaction.finished)) {
114
+ yield this.transaction.commit();
115
+ }
116
+ });
117
+ }
118
+ exec(instruction, node, prevJob) {
119
+ return __awaiter(this, void 0, void 0, function* () {
120
+ let job;
121
+ try {
122
+ // call instruction to get result and status
123
+ job = yield instruction.call(node, prevJob, this);
124
+ if (!job) {
125
+ return null;
126
+ }
127
+ }
128
+ catch (err) {
129
+ // for uncaught error, set to rejected
130
+ job = {
131
+ result: err instanceof Error
132
+ ? { message: err.message, stack: process.env.NODE_ENV === 'production' ? [] : err.stack }
133
+ : err,
134
+ status: constants_1.JOB_STATUS.REJECTED,
135
+ };
136
+ // if previous job is from resuming
137
+ if (prevJob && prevJob.nodeId === node.id) {
138
+ prevJob.set(job);
139
+ job = prevJob;
140
+ }
141
+ }
142
+ let savedJob;
143
+ // TODO(optimize): many checking of resuming or new could be improved
144
+ // could be implemented separately in exec() / resume()
145
+ if (job instanceof database_1.Model) {
146
+ savedJob = (yield job.save({ transaction: this.transaction }));
147
+ }
148
+ else {
149
+ const upstreamId = prevJob instanceof database_1.Model ? prevJob.get('id') : null;
150
+ savedJob = yield this.saveJob(Object.assign({ nodeId: node.id, upstreamId }, job));
151
+ }
152
+ if (savedJob.status === constants_1.JOB_STATUS.RESOLVED && node.downstream) {
153
+ // run next node
154
+ return this.run(node.downstream, savedJob);
155
+ }
156
+ // all nodes in scope have been executed
157
+ return this.end(node, savedJob);
158
+ });
159
+ }
160
+ run(node, input) {
161
+ return __awaiter(this, void 0, void 0, function* () {
162
+ const { run } = instructions_1.default.get(node.type);
163
+ if (typeof run !== 'function') {
164
+ return Promise.reject(new Error('`run` should be implemented for customized execution of the node'));
165
+ }
166
+ return this.exec(run, node, input);
167
+ });
168
+ }
169
+ // parent node should take over the control
170
+ end(node, job) {
171
+ const parentNode = this.findBranchParentNode(node);
172
+ // no parent, means on main flow
173
+ if (parentNode) {
174
+ return this.recall(parentNode, job);
175
+ }
176
+ // really done for all nodes
177
+ // * should mark execution as done with last job status
178
+ return this.exit(job);
179
+ }
180
+ recall(node, job) {
181
+ return __awaiter(this, void 0, void 0, function* () {
182
+ const { resume } = instructions_1.default.get(node.type);
183
+ if (typeof resume !== 'function') {
184
+ return Promise.reject(new Error('`resume` should be implemented because the node made branch'));
185
+ }
186
+ return this.exec(resume, node, job);
187
+ });
188
+ }
189
+ exit(job) {
190
+ return __awaiter(this, void 0, void 0, function* () {
191
+ const status = job ? ExecutionModel.StatusMap[job.status] : constants_1.EXECUTION_STATUS.RESOLVED;
192
+ yield this.update({ status }, { transaction: this.transaction });
193
+ return null;
194
+ });
195
+ }
196
+ // TODO(optimize)
197
+ saveJob(payload) {
198
+ return __awaiter(this, void 0, void 0, function* () {
199
+ const { database } = this.constructor;
200
+ const { model } = database.getCollection('jobs');
201
+ const [job] = (yield model.upsert(Object.assign(Object.assign({}, payload), { executionId: this.id }), { transaction: this.transaction }));
202
+ this.jobsMap.set(job.id, job);
203
+ this.jobsMapByNodeId[job.nodeId] = job.result;
204
+ return job;
205
+ });
206
+ }
207
+ // find the first node in current branch
208
+ findBranchStartNode(node) {
209
+ for (let n = node; n; n = n.upstream) {
210
+ if (n.branchIndex !== null) {
211
+ return n;
212
+ }
213
+ }
214
+ return null;
215
+ }
216
+ // find the node start current branch
217
+ findBranchParentNode(node) {
218
+ for (let n = node; n; n = n.upstream) {
219
+ if (n.branchIndex !== null) {
220
+ return n.upstream;
221
+ }
222
+ }
223
+ return null;
224
+ }
225
+ findBranchParentJob(job, node) {
226
+ for (let j = job; j; j = this.jobsMap.get(j.upstreamId)) {
227
+ if (j.nodeId === node.id) {
228
+ return j;
229
+ }
230
+ }
231
+ return null;
232
+ }
233
+ getParsedValue(value, node) {
234
+ const injectedFns = {};
235
+ const scope = {
236
+ execution: this,
237
+ node
238
+ };
239
+ for (let [name, fn] of calculators_1.default.getEntities()) {
240
+ injectedFns[name] = fn.bind(scope);
241
+ }
242
+ return (0, json_templates_1.default)(value)({
243
+ $context: this.context,
244
+ $jobsMapByNodeId: this.jobsMapByNodeId,
245
+ $fn: injectedFns
246
+ });
247
+ }
248
+ }
249
+ exports.default = ExecutionModel;
250
+ ExecutionModel.StatusMap = {
251
+ [constants_1.JOB_STATUS.PENDING]: constants_1.EXECUTION_STATUS.STARTED,
252
+ [constants_1.JOB_STATUS.RESOLVED]: constants_1.EXECUTION_STATUS.RESOLVED,
253
+ [constants_1.JOB_STATUS.REJECTED]: constants_1.EXECUTION_STATUS.REJECTED,
254
+ [constants_1.JOB_STATUS.CANCELLED]: constants_1.EXECUTION_STATUS.CANCELLED,
255
+ };
256
+ //# sourceMappingURL=Execution.js.map