@acorex/platform 21.0.0-next.8 → 21.0.0-next.85
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/contracts/README.md +3 -0
- package/fesm2022/acorex-platform-auth.mjs +201 -81
- package/fesm2022/acorex-platform-auth.mjs.map +1 -1
- package/fesm2022/acorex-platform-common-common-settings.provider-Ytey9uhY.mjs +177 -0
- package/fesm2022/acorex-platform-common-common-settings.provider-Ytey9uhY.mjs.map +1 -0
- package/fesm2022/acorex-platform-common.mjs +4490 -880
- package/fesm2022/acorex-platform-common.mjs.map +1 -1
- package/fesm2022/acorex-platform-contracts.mjs +38 -0
- package/fesm2022/acorex-platform-contracts.mjs.map +1 -0
- package/fesm2022/acorex-platform-core.mjs +2612 -667
- package/fesm2022/acorex-platform-core.mjs.map +1 -1
- package/fesm2022/acorex-platform-domain.mjs +557 -826
- package/fesm2022/acorex-platform-domain.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-builder.mjs +1255 -209
- package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-CXEdvDTf.mjs +121 -0
- package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-CXEdvDTf.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-components.mjs +6493 -1920
- package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-designer.mjs +612 -287
- package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-entity-attachments-page.component-CwG6n_Yb.mjs +376 -0
- package/fesm2022/acorex-platform-layout-entity-attachments-page.component-CwG6n_Yb.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-entity-file-list-popup.component--IeMZLIr.mjs +100 -0
- package/fesm2022/acorex-platform-layout-entity-file-list-popup.component--IeMZLIr.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-entity.mjs +22502 -9964
- package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-views.mjs +1395 -387
- package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widget-core.mjs +2226 -524
- package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
- package/fesm2022/{acorex-platform-layout-widgets-button-widget-designer.component-C3VoBb_b.mjs → acorex-platform-layout-widgets-button-widget-designer.component-Dy7jF-oD.mjs} +10 -10
- package/fesm2022/acorex-platform-layout-widgets-button-widget-designer.component-Dy7jF-oD.mjs.map +1 -0
- package/fesm2022/{acorex-platform-layout-widgets-image-preview.popup-V31OpYah.mjs → acorex-platform-layout-widgets-image-preview.popup-C_EPAvCU.mjs} +6 -7
- package/fesm2022/acorex-platform-layout-widgets-image-preview.popup-C_EPAvCU.mjs.map +1 -0
- package/fesm2022/{acorex-platform-layout-widgets-page-widget-designer.component-BtZMBxYp.mjs → acorex-platform-layout-widgets-page-widget-designer.component-D10yO28c.mjs} +12 -12
- package/fesm2022/acorex-platform-layout-widgets-page-widget-designer.component-D10yO28c.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-J0zcGKBX.mjs +116 -0
- package/fesm2022/acorex-platform-layout-widgets-repeater-widget-column.component-J0zcGKBX.mjs.map +1 -0
- package/fesm2022/{acorex-platform-layout-widgets-tabular-data-edit-popup.component-Ck7-wpT2.mjs → acorex-platform-layout-widgets-tabular-data-edit-popup.component-DjpZU6gz.mjs} +6 -6
- package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-DjpZU6gz.mjs.map +1 -0
- package/fesm2022/{acorex-platform-layout-widgets-tabular-data-view-popup.component-y8vjUiVs.mjs → acorex-platform-layout-widgets-tabular-data-view-popup.component-gX-3Kx9I.mjs} +5 -5
- package/fesm2022/acorex-platform-layout-widgets-tabular-data-view-popup.component-gX-3Kx9I.mjs.map +1 -0
- package/fesm2022/{acorex-platform-layout-widgets-text-block-widget-designer.component-Df1BFkSa.mjs → acorex-platform-layout-widgets-text-block-widget-designer.component-Vo4fWHtX.mjs} +6 -6
- package/fesm2022/acorex-platform-layout-widgets-text-block-widget-designer.component-Vo4fWHtX.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-widgets.mjs +18746 -16718
- package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
- package/fesm2022/acorex-platform-native.mjs +8 -7
- package/fesm2022/acorex-platform-native.mjs.map +1 -1
- package/fesm2022/acorex-platform-runtime.mjs +391 -166
- package/fesm2022/acorex-platform-runtime.mjs.map +1 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-CWLfNqV0.mjs +160 -0
- package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-CWLfNqV0.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-C7cT82K2.mjs +120 -0
- package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-C7cT82K2.mjs.map +1 -0
- package/fesm2022/{acorex-platform-themes-default-entity-master-single-view.component-eMBby9k4.mjs → acorex-platform-themes-default-entity-master-single-view.component-Br9p5aXT.mjs} +21 -28
- package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-Br9p5aXT.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-default-error-401.component-B1nsdpTY.mjs +48 -0
- package/fesm2022/acorex-platform-themes-default-error-401.component-B1nsdpTY.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-default-error-404.component-D4UvRe8u.mjs +42 -0
- package/fesm2022/acorex-platform-themes-default-error-404.component-D4UvRe8u.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-default-error-offline.component-DR6G8gPC.mjs +19 -0
- package/fesm2022/acorex-platform-themes-default-error-offline.component-DR6G8gPC.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-default.mjs +2337 -94
- package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
- package/fesm2022/{acorex-platform-themes-shared-icon-chooser-column.component-C0EpfU2k.mjs → acorex-platform-themes-shared-icon-chooser-column.component-CqkWJYdv.mjs} +6 -6
- package/fesm2022/acorex-platform-themes-shared-icon-chooser-column.component-CqkWJYdv.mjs.map +1 -0
- package/fesm2022/{acorex-platform-themes-shared-icon-chooser-view.component-9W52W6Nu.mjs → acorex-platform-themes-shared-icon-chooser-view.component-BOTuLdWN.mjs} +6 -6
- package/fesm2022/acorex-platform-themes-shared-icon-chooser-view.component-BOTuLdWN.mjs.map +1 -0
- package/fesm2022/{acorex-platform-themes-shared-settings.provider-DSs1o1M6.mjs → acorex-platform-themes-shared-settings.provider-BjuzSe0T.mjs} +52 -33
- package/fesm2022/acorex-platform-themes-shared-settings.provider-BjuzSe0T.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-D566Kdvy.mjs +94 -0
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-D566Kdvy.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-D7-rCGl7.mjs +86 -0
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-D7-rCGl7.mjs.map +1 -0
- package/fesm2022/acorex-platform-themes-shared.mjs +793 -612
- package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
- package/fesm2022/acorex-platform-workflow.mjs +997 -274
- package/fesm2022/acorex-platform-workflow.mjs.map +1 -1
- package/fesm2022/acorex-platform.mjs.map +1 -1
- package/package.json +41 -35
- package/{auth/index.d.ts → types/acorex-platform-auth.d.ts} +40 -19
- package/types/acorex-platform-common.d.ts +3673 -0
- package/types/acorex-platform-contracts.d.ts +940 -0
- package/{core/index.d.ts → types/acorex-platform-core.d.ts} +1029 -170
- package/{domain/index.d.ts → types/acorex-platform-domain.d.ts} +744 -412
- package/{layout/builder/index.d.ts → types/acorex-platform-layout-builder.d.ts} +262 -55
- package/types/acorex-platform-layout-components.d.ts +3329 -0
- package/{layout/designer/index.d.ts → types/acorex-platform-layout-designer.d.ts} +96 -18
- package/types/acorex-platform-layout-entity.d.ts +4512 -0
- package/{layout/views/index.d.ts → types/acorex-platform-layout-views.d.ts} +334 -91
- package/{layout/widget-core/index.d.ts → types/acorex-platform-layout-widget-core.d.ts} +438 -162
- package/{layout/widgets/index.d.ts → types/acorex-platform-layout-widgets.d.ts} +1152 -507
- package/{native/index.d.ts → types/acorex-platform-native.d.ts} +0 -7
- package/types/acorex-platform-runtime.d.ts +571 -0
- package/{themes/default/index.d.ts → types/acorex-platform-themes-default.d.ts} +268 -11
- package/{themes/shared/index.d.ts → types/acorex-platform-themes-shared.d.ts} +30 -2
- package/{workflow/index.d.ts → types/acorex-platform-workflow.d.ts} +436 -748
- package/common/index.d.ts +0 -2470
- package/fesm2022/acorex-platform-common-common-settings.provider-zhqNP3xb.mjs +0 -71
- package/fesm2022/acorex-platform-common-common-settings.provider-zhqNP3xb.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-button-widget-designer.component-C3VoBb_b.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-CxrsI6Hn.mjs +0 -135
- package/fesm2022/acorex-platform-layout-widgets-file-list-popup.component-CxrsI6Hn.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-image-preview.popup-V31OpYah.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-page-widget-designer.component-BtZMBxYp.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-tabular-data-edit-popup.component-Ck7-wpT2.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-tabular-data-view-popup.component-y8vjUiVs.mjs.map +0 -1
- package/fesm2022/acorex-platform-layout-widgets-text-block-widget-designer.component-Df1BFkSa.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-VIGuU5M4.mjs +0 -157
- package/fesm2022/acorex-platform-themes-default-entity-master-create-view.component-VIGuU5M4.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-D3qZa5fM.mjs +0 -1542
- package/fesm2022/acorex-platform-themes-default-entity-master-list-view.component-D3qZa5fM.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-Ua3ZA5hk.mjs +0 -101
- package/fesm2022/acorex-platform-themes-default-entity-master-modify-view.component-Ua3ZA5hk.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-entity-master-single-view.component-eMBby9k4.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-error-401.component-cfREo88K.mjs +0 -31
- package/fesm2022/acorex-platform-themes-default-error-401.component-cfREo88K.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-error-404.component-CdCV5ZoA.mjs +0 -25
- package/fesm2022/acorex-platform-themes-default-error-404.component-CdCV5ZoA.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-default-error-offline.component-E7SzBcAt.mjs +0 -19
- package/fesm2022/acorex-platform-themes-default-error-offline.component-E7SzBcAt.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-shared-icon-chooser-column.component-C0EpfU2k.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-shared-icon-chooser-view.component-9W52W6Nu.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-shared-settings.provider-DSs1o1M6.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-Dz0cylyQ.mjs +0 -65
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-column.component-Dz0cylyQ.mjs.map +0 -1
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-DY0JtT1v.mjs +0 -64
- package/fesm2022/acorex-platform-themes-shared-theme-color-chooser-view.component-DY0JtT1v.mjs.map +0 -1
- package/layout/components/index.d.ts +0 -1670
- package/layout/entity/index.d.ts +0 -2294
- package/runtime/index.d.ts +0 -307
- /package/{index.d.ts → types/acorex-platform.d.ts} +0 -0
|
@@ -2,7 +2,8 @@ import * as i0 from '@angular/core';
|
|
|
2
2
|
import { Injectable, inject, InjectionToken, Optional, Inject, NgModule } from '@angular/core';
|
|
3
3
|
import { Subject, filter } from 'rxjs';
|
|
4
4
|
import { cloneDeep, get, set } from 'lodash-es';
|
|
5
|
-
import { setSmart, AXPDataGenerator } from '@acorex/platform/core';
|
|
5
|
+
import { setSmart, AXPExpressionEvaluatorService, AXPDataGenerator } from '@acorex/platform/core';
|
|
6
|
+
import { AXTranslationService } from '@acorex/core/translation';
|
|
6
7
|
import { AXPCommandService } from '@acorex/platform/runtime';
|
|
7
8
|
|
|
8
9
|
class AXPWorkflowError extends Error {
|
|
@@ -23,16 +24,73 @@ class AXPWorkflowEventService {
|
|
|
23
24
|
get events$() {
|
|
24
25
|
return this.eventSubject.asObservable();
|
|
25
26
|
}
|
|
26
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
27
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
27
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowEventService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
28
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowEventService, providedIn: 'root' }); }
|
|
28
29
|
}
|
|
29
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
30
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowEventService, decorators: [{
|
|
30
31
|
type: Injectable,
|
|
31
32
|
args: [{
|
|
32
33
|
providedIn: 'root',
|
|
33
34
|
}]
|
|
34
35
|
}] });
|
|
35
36
|
|
|
37
|
+
class AXPWorkflowContext {
|
|
38
|
+
constructor(initialData = {}) {
|
|
39
|
+
this.variables = {};
|
|
40
|
+
this.stepOutputs = new Map();
|
|
41
|
+
this.variables = cloneDeep(initialData);
|
|
42
|
+
}
|
|
43
|
+
setVariable(key, value) {
|
|
44
|
+
setSmart(this.variables, key, value);
|
|
45
|
+
}
|
|
46
|
+
setVariables(context = {}) {
|
|
47
|
+
this.variables = { ...this.variables, ...context };
|
|
48
|
+
}
|
|
49
|
+
getVariable(key) {
|
|
50
|
+
return !key ? this.variables : get(this.variables, key);
|
|
51
|
+
}
|
|
52
|
+
setOutput(key, output) {
|
|
53
|
+
this.stepOutputs.set(key, output);
|
|
54
|
+
}
|
|
55
|
+
setOutputs(values) {
|
|
56
|
+
this.stepOutputs = new Map([...this.stepOutputs, ...values]);
|
|
57
|
+
}
|
|
58
|
+
getOutput(key) {
|
|
59
|
+
return this.stepOutputs.get(key);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
class AXPWorkflowAction {
|
|
63
|
+
constructor() {
|
|
64
|
+
this.eventService = inject(AXPWorkflowEventService);
|
|
65
|
+
}
|
|
66
|
+
dispatch(event) {
|
|
67
|
+
this.eventService.dispatch(event);
|
|
68
|
+
}
|
|
69
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowAction, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
70
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowAction }); }
|
|
71
|
+
}
|
|
72
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowAction, decorators: [{
|
|
73
|
+
type: Injectable
|
|
74
|
+
}] });
|
|
75
|
+
class AXPWorkflowFunction {
|
|
76
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowFunction, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
77
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowFunction }); }
|
|
78
|
+
}
|
|
79
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowFunction, decorators: [{
|
|
80
|
+
type: Injectable
|
|
81
|
+
}] });
|
|
82
|
+
function createWorkFlowEvent(type) {
|
|
83
|
+
const eventCreator = (payload) => ({ type, payload });
|
|
84
|
+
eventCreator.type = type;
|
|
85
|
+
return eventCreator;
|
|
86
|
+
}
|
|
87
|
+
function ofType(...allowedTypes) {
|
|
88
|
+
return filter((event) => allowedTypes.some((type) => event.type === type.type));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
//#region ---- Contracts barrel ----
|
|
92
|
+
//#endregion
|
|
93
|
+
|
|
36
94
|
class AXPWorkflowRegistryService {
|
|
37
95
|
constructor() {
|
|
38
96
|
this.functionsMap = new Map();
|
|
@@ -116,78 +174,24 @@ class AXPWorkflowRegistryService {
|
|
|
116
174
|
});
|
|
117
175
|
}
|
|
118
176
|
}
|
|
119
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
120
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
177
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
178
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowRegistryService, providedIn: 'root' }); }
|
|
121
179
|
}
|
|
122
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
180
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowRegistryService, decorators: [{
|
|
123
181
|
type: Injectable,
|
|
124
182
|
args: [{
|
|
125
183
|
providedIn: 'root',
|
|
126
184
|
}]
|
|
127
185
|
}] });
|
|
128
186
|
|
|
129
|
-
class AXPWorkflowContext {
|
|
130
|
-
constructor(initialData = {}) {
|
|
131
|
-
this.variables = {};
|
|
132
|
-
this.stepOutputs = new Map();
|
|
133
|
-
this.variables = cloneDeep(initialData);
|
|
134
|
-
}
|
|
135
|
-
setVariable(key, value) {
|
|
136
|
-
setSmart(this.variables, key, value);
|
|
137
|
-
}
|
|
138
|
-
setVariables(context = {}) {
|
|
139
|
-
this.variables = { ...this.variables, ...context };
|
|
140
|
-
}
|
|
141
|
-
getVariable(key) {
|
|
142
|
-
return !key ? this.variables : get(this.variables, key);
|
|
143
|
-
}
|
|
144
|
-
setOutput(key, output) {
|
|
145
|
-
this.stepOutputs.set(key, output);
|
|
146
|
-
}
|
|
147
|
-
setOutputs(values) {
|
|
148
|
-
this.stepOutputs = new Map([...this.stepOutputs, ...values]);
|
|
149
|
-
}
|
|
150
|
-
getOutput(key) {
|
|
151
|
-
return this.stepOutputs.get(key);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
class AXPWorkflowAction {
|
|
155
|
-
constructor() {
|
|
156
|
-
this.eventService = inject(AXPWorkflowEventService);
|
|
157
|
-
}
|
|
158
|
-
dispatch(event) {
|
|
159
|
-
this.eventService.dispatch(event);
|
|
160
|
-
}
|
|
161
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPWorkflowAction, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
162
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPWorkflowAction }); }
|
|
163
|
-
}
|
|
164
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPWorkflowAction, decorators: [{
|
|
165
|
-
type: Injectable
|
|
166
|
-
}] });
|
|
167
|
-
class AXPWorkflowFunction {
|
|
168
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPWorkflowFunction, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
169
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPWorkflowFunction }); }
|
|
170
|
-
}
|
|
171
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPWorkflowFunction, decorators: [{
|
|
172
|
-
type: Injectable
|
|
173
|
-
}] });
|
|
174
|
-
function createWorkFlowEvent(type) {
|
|
175
|
-
const eventCreator = (payload) => ({ type, payload });
|
|
176
|
-
eventCreator.type = type;
|
|
177
|
-
return eventCreator;
|
|
178
|
-
}
|
|
179
|
-
function ofType(...allowedTypes) {
|
|
180
|
-
return filter((event) => allowedTypes.some((type) => event.type === type.type));
|
|
181
|
-
}
|
|
182
|
-
|
|
183
187
|
class AXPWorkflowDecideAction extends AXPWorkflowAction {
|
|
184
188
|
async execute(context) {
|
|
185
189
|
// its a fake action
|
|
186
190
|
}
|
|
187
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
188
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
191
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowDecideAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
192
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowDecideAction, providedIn: 'root' }); }
|
|
189
193
|
}
|
|
190
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
194
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowDecideAction, decorators: [{
|
|
191
195
|
type: Injectable,
|
|
192
196
|
args: [{
|
|
193
197
|
providedIn: 'root',
|
|
@@ -373,10 +377,10 @@ class AXPWorkflowService {
|
|
|
373
377
|
}
|
|
374
378
|
return this.injector.get(functionType);
|
|
375
379
|
}
|
|
376
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
377
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
380
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowService, deps: [{ token: AXPWorkflowRegistryService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
381
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowService, providedIn: 'root' }); }
|
|
378
382
|
}
|
|
379
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
383
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowService, decorators: [{
|
|
380
384
|
type: Injectable,
|
|
381
385
|
args: [{
|
|
382
386
|
providedIn: 'root',
|
|
@@ -401,28 +405,16 @@ class AXPStartWorkflowAction extends AXPWorkflowAction {
|
|
|
401
405
|
throw e;
|
|
402
406
|
}
|
|
403
407
|
}
|
|
404
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
405
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
408
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPStartWorkflowAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
409
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPStartWorkflowAction, providedIn: 'root' }); }
|
|
406
410
|
}
|
|
407
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
411
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPStartWorkflowAction, decorators: [{
|
|
408
412
|
type: Injectable,
|
|
409
413
|
args: [{
|
|
410
414
|
providedIn: 'root',
|
|
411
415
|
}]
|
|
412
416
|
}] });
|
|
413
417
|
|
|
414
|
-
/**
|
|
415
|
-
* Injection token for workflow definition loaders.
|
|
416
|
-
* Multiple loaders can be provided (multi: true).
|
|
417
|
-
*/
|
|
418
|
-
const AXP_WORKFLOW_DEFINITION_LOADER = new InjectionToken('AXP_WORKFLOW_DEFINITION_LOADER');
|
|
419
|
-
|
|
420
|
-
// ============================================
|
|
421
|
-
// WORKFLOW INSTANCE v3.0.0 TYPES
|
|
422
|
-
// Based on Elsa Workflow Instance schema: https://elsaworkflows.io/schemas/workflow-instance/v3.0.0/schema.json
|
|
423
|
-
// Compatible with Elsa backend while using ACoreX naming conventions
|
|
424
|
-
// ============================================
|
|
425
|
-
|
|
426
418
|
const AXP_ACTIVITY_PROVIDER = new InjectionToken('AXP_ACTIVITY_PROVIDER', {
|
|
427
419
|
factory: () => [],
|
|
428
420
|
});
|
|
@@ -598,6 +590,19 @@ class AXPActivityDefinitionService {
|
|
|
598
590
|
this.pendingActivityRequests.set(name, requestPromise);
|
|
599
591
|
return requestPromise;
|
|
600
592
|
}
|
|
593
|
+
/**
|
|
594
|
+
* Get all activity definitions (flat list) by loading root categories and their activities.
|
|
595
|
+
* Used by activity selector UIs (e.g. automation command configurator).
|
|
596
|
+
*/
|
|
597
|
+
async getAllActivities() {
|
|
598
|
+
const categories = await this.getCategories(undefined);
|
|
599
|
+
const all = [];
|
|
600
|
+
for (const cat of categories) {
|
|
601
|
+
const activities = await this.getActivitiesByCategoryId(cat.id);
|
|
602
|
+
all.push(...activities);
|
|
603
|
+
}
|
|
604
|
+
return all;
|
|
605
|
+
}
|
|
601
606
|
/**
|
|
602
607
|
* Get category ID containing a specific activity definition
|
|
603
608
|
*
|
|
@@ -615,7 +620,7 @@ class AXPActivityDefinitionService {
|
|
|
615
620
|
if (definition && definition.category) {
|
|
616
621
|
// Try to find category by name/id
|
|
617
622
|
const categories = await this.getCategories();
|
|
618
|
-
const found = categories.find(cat => cat.id === definition.category
|
|
623
|
+
const found = categories.find((cat) => cat.id === definition.category?.id);
|
|
619
624
|
if (found) {
|
|
620
625
|
return found.id;
|
|
621
626
|
}
|
|
@@ -842,10 +847,10 @@ class AXPActivityDefinitionService {
|
|
|
842
847
|
this.pendingActivitiesRequests.clear();
|
|
843
848
|
this.pendingActivityRequests.clear();
|
|
844
849
|
}
|
|
845
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
846
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
850
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPActivityDefinitionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
851
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPActivityDefinitionService, providedIn: 'root' }); }
|
|
847
852
|
}
|
|
848
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
853
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPActivityDefinitionService, decorators: [{
|
|
849
854
|
type: Injectable,
|
|
850
855
|
args: [{
|
|
851
856
|
providedIn: 'root',
|
|
@@ -858,61 +863,357 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
858
863
|
*/
|
|
859
864
|
const AXP_WORKFLOW_ENGINE = new InjectionToken('AXP_WORKFLOW_ENGINE');
|
|
860
865
|
|
|
866
|
+
//#region ---- Error Codes ----
|
|
867
|
+
/**
|
|
868
|
+
* Stable workflow engine error codes for UI branching (toasts, take-over flow, etc.).
|
|
869
|
+
*/
|
|
870
|
+
const AXP_WORKFLOW_ERROR_CODES = {
|
|
871
|
+
TASK_NOT_ASSIGNEE: 'WORKFLOW_TASK_NOT_ASSIGNEE',
|
|
872
|
+
CLAIM_REQUIRED: 'WORKFLOW_CLAIM_REQUIRED',
|
|
873
|
+
REASSIGN_NOT_ALLOWED: 'WORKFLOW_REASSIGN_NOT_ALLOWED',
|
|
874
|
+
};
|
|
875
|
+
//#endregion
|
|
876
|
+
//#region ---- Engine Error ----
|
|
877
|
+
/**
|
|
878
|
+
* Business-rule failure from {@link AXPWorkflowEngine} (expected, user-facing).
|
|
879
|
+
*/
|
|
880
|
+
class AXPWorkflowEngineError extends Error {
|
|
881
|
+
constructor(message, code, details) {
|
|
882
|
+
super(message);
|
|
883
|
+
this.code = code;
|
|
884
|
+
this.details = details;
|
|
885
|
+
this.name = 'AXPWorkflowEngineError';
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* Resolves a stable error code from an unknown thrown value.
|
|
890
|
+
*/
|
|
891
|
+
function getWorkflowEngineErrorCode(error) {
|
|
892
|
+
if (error instanceof AXPWorkflowEngineError) {
|
|
893
|
+
return error.code;
|
|
894
|
+
}
|
|
895
|
+
return undefined;
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Resolves a user-facing message and optional code from an unknown thrown value.
|
|
899
|
+
*/
|
|
900
|
+
function getWorkflowEngineErrorInfo(error) {
|
|
901
|
+
if (error instanceof AXPWorkflowEngineError) {
|
|
902
|
+
return { message: error.message, code: error.code };
|
|
903
|
+
}
|
|
904
|
+
if (error instanceof Error) {
|
|
905
|
+
return { message: error.message };
|
|
906
|
+
}
|
|
907
|
+
return { message: 'An unexpected workflow error occurred' };
|
|
908
|
+
}
|
|
909
|
+
//#endregion
|
|
910
|
+
|
|
911
|
+
/**
|
|
912
|
+
* Activity types that use the task board (suspend until user acts via inbox), not inline interactive execution.
|
|
913
|
+
*/
|
|
914
|
+
const AXP_WORKFLOW_TASK_BOARD_ACTIVITY_TYPES = [
|
|
915
|
+
'workflow-activity:human-task',
|
|
916
|
+
'workflow-activity:cartable',
|
|
917
|
+
];
|
|
918
|
+
function axpIsWorkflowTaskBoardActivityType(activityType) {
|
|
919
|
+
return !!activityType && AXP_WORKFLOW_TASK_BOARD_ACTIVITY_TYPES.includes(activityType);
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
//#endregion
|
|
923
|
+
/**
|
|
924
|
+
* Workflow Expression Scope Service
|
|
925
|
+
*
|
|
926
|
+
* Shared service for building expression evaluation scope from workflow data.
|
|
927
|
+
* Used by both Local Engine and Mock Runtime to manage workflow data (inputs, variables, outputs).
|
|
928
|
+
*
|
|
929
|
+
* Responsibilities:
|
|
930
|
+
* - Build expression evaluation scope from workflow state
|
|
931
|
+
* - Provide context.eval() function for accessing workflow data
|
|
932
|
+
* - Manage workflow data structure (inputs, variables, outputs)
|
|
933
|
+
*
|
|
934
|
+
* This service does NOT:
|
|
935
|
+
* - Execute activities
|
|
936
|
+
* - Evaluate expressions (delegates to AXPExpressionEvaluatorService)
|
|
937
|
+
* - Manage workflow state (handled by runtime)
|
|
938
|
+
*
|
|
939
|
+
* @example
|
|
940
|
+
* ```typescript
|
|
941
|
+
* const scopeService = inject(WorkflowExpressionScopeService);
|
|
942
|
+
*
|
|
943
|
+
* // Build scope from workflow state
|
|
944
|
+
* const scope = scopeService.buildScope({
|
|
945
|
+
* inputs: state.input || {},
|
|
946
|
+
* variables: state.variables || {},
|
|
947
|
+
* outputs: activityOutputs
|
|
948
|
+
* });
|
|
949
|
+
*
|
|
950
|
+
* // Or build from state directly
|
|
951
|
+
* const scope = scopeService.buildScopeFromState(state, activityOutputs);
|
|
952
|
+
* ```
|
|
953
|
+
*/
|
|
954
|
+
class WorkflowExpressionScopeService {
|
|
955
|
+
//#region ---- Private Helpers (dot-notation input normalization) ----
|
|
956
|
+
/**
|
|
957
|
+
* Collect dot-notation key-value pairs from nested objects so that e.g.
|
|
958
|
+
* { metadata: { "metadata.questionnaire.id": "x" } } becomes { "metadata.questionnaire.id": "x" } at root.
|
|
959
|
+
* Top-level non-dot keys are kept as-is.
|
|
960
|
+
*/
|
|
961
|
+
flattenDotKeysFromTree(obj) {
|
|
962
|
+
if (obj === null || typeof obj !== 'object')
|
|
963
|
+
return obj;
|
|
964
|
+
const result = {};
|
|
965
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
966
|
+
if (key.includes('.')) {
|
|
967
|
+
result[key] = value;
|
|
968
|
+
}
|
|
969
|
+
else if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
|
|
970
|
+
for (const [k, v] of Object.entries(value)) {
|
|
971
|
+
if (k.includes('.')) {
|
|
972
|
+
result[k] = v;
|
|
973
|
+
}
|
|
974
|
+
else {
|
|
975
|
+
result[key + '.' + k] = v;
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
else {
|
|
980
|
+
result[key] = value;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
return result;
|
|
984
|
+
}
|
|
985
|
+
/**
|
|
986
|
+
* Expand flat keys with dots into nested objects.
|
|
987
|
+
* e.g. { "metadata.questionnaire.id": "x" } -> { metadata: { questionnaire: { id: "x" } } }.
|
|
988
|
+
*/
|
|
989
|
+
expandDotKeys(obj) {
|
|
990
|
+
if (obj === null || typeof obj !== 'object')
|
|
991
|
+
return obj;
|
|
992
|
+
const result = {};
|
|
993
|
+
const dotKeys = [];
|
|
994
|
+
const simpleKeys = [];
|
|
995
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
996
|
+
if (key.includes('.')) {
|
|
997
|
+
dotKeys.push([key, value]);
|
|
998
|
+
}
|
|
999
|
+
else {
|
|
1000
|
+
simpleKeys.push([key, value]);
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
for (const [key, value] of dotKeys) {
|
|
1004
|
+
const parts = key.split('.');
|
|
1005
|
+
let current = result;
|
|
1006
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
1007
|
+
const part = parts[i];
|
|
1008
|
+
if (!(part in current) || typeof current[part] !== 'object' || current[part] === null) {
|
|
1009
|
+
current[part] = {};
|
|
1010
|
+
}
|
|
1011
|
+
current = current[part];
|
|
1012
|
+
}
|
|
1013
|
+
current[parts[parts.length - 1]] = value;
|
|
1014
|
+
}
|
|
1015
|
+
for (const [key, value] of simpleKeys) {
|
|
1016
|
+
result[key] = value;
|
|
1017
|
+
}
|
|
1018
|
+
return result;
|
|
1019
|
+
}
|
|
1020
|
+
/**
|
|
1021
|
+
* Normalize workflow input so that flat dot-notation keys (e.g. from form schema
|
|
1022
|
+
* "metadata.questionnaire.id") become nested for expression access (inputs.metadata.questionnaire.id).
|
|
1023
|
+
*/
|
|
1024
|
+
normalizeInputs(input) {
|
|
1025
|
+
if (!input || typeof input !== 'object')
|
|
1026
|
+
return {};
|
|
1027
|
+
const flattened = this.flattenDotKeysFromTree(input);
|
|
1028
|
+
return this.expandDotKeys(flattened);
|
|
1029
|
+
}
|
|
1030
|
+
//#endregion
|
|
1031
|
+
//#region ---- Public Methods ----
|
|
1032
|
+
/**
|
|
1033
|
+
* Build expression evaluation scope for workflow activities.
|
|
1034
|
+
*
|
|
1035
|
+
* Provides workflow-specific data (inputs, variables, outputs) and context.eval() function.
|
|
1036
|
+
* Other data (session, current user, etc.) are provided by expression evaluator scope providers.
|
|
1037
|
+
*
|
|
1038
|
+
* Scope includes:
|
|
1039
|
+
* - inputs: Workflow input values (accessible as inputs.propertyName)
|
|
1040
|
+
* - variables: Workflow state variables (accessible as variables.propertyName or vars.propertyName)
|
|
1041
|
+
* - outputs: Previous activity outputs (accessible as outputs.activityId)
|
|
1042
|
+
* - context.eval(path): Function to access nested properties from workflow data
|
|
1043
|
+
*
|
|
1044
|
+
* Expressions can use:
|
|
1045
|
+
* - {{inputs.userName}} - Direct access to workflow input
|
|
1046
|
+
* - {{variables.someVar}} or {{vars.someVar}} - Direct access to workflow variable
|
|
1047
|
+
* - {{outputs.activityId.property}} - Direct access to previous activity output
|
|
1048
|
+
* - {{context.eval("inputs.userName")}} - Access via context.eval (supports nested paths)
|
|
1049
|
+
* - {{context.eval("variables.someVar")}} - Access variables via context.eval
|
|
1050
|
+
* - {{context.eval("outputs.activityId.property")}} - Access outputs via context.eval
|
|
1051
|
+
* - {{session.currentUser().name}} - Access current user via expression evaluator scope providers
|
|
1052
|
+
*
|
|
1053
|
+
* The context.eval() function provides a unified way to access all workflow data,
|
|
1054
|
+
* similar to how entity-detail-list uses context.eval() to access parent data.
|
|
1055
|
+
*
|
|
1056
|
+
* @param context - Workflow expression context containing inputs, variables, and outputs
|
|
1057
|
+
* @returns Expression evaluator scope with workflow data and context.eval() function
|
|
1058
|
+
*/
|
|
1059
|
+
buildScope(context) {
|
|
1060
|
+
// Normalize inputs so flat dot-notation keys (e.g. metadata.questionnaire.id from forms) become nested for expressions
|
|
1061
|
+
const inputs = this.normalizeInputs(context.inputs || {});
|
|
1062
|
+
// Build merged workflow data object for context.eval()
|
|
1063
|
+
// This allows expressions like: context.eval("inputs.userName") or context.eval("variables.count")
|
|
1064
|
+
const workflowData = {
|
|
1065
|
+
inputs,
|
|
1066
|
+
variables: context.variables || {},
|
|
1067
|
+
vars: context.variables || {}, // Alias for convenience
|
|
1068
|
+
outputs: context.outputs || {},
|
|
1069
|
+
};
|
|
1070
|
+
// Build scope object with workflow-specific data and context.eval()
|
|
1071
|
+
// Note: AXPExpressionEvaluatorScope type expects { [namespace]: { [name]: Function } }
|
|
1072
|
+
// but evaluate() method actually accepts flat objects with values too
|
|
1073
|
+
// We'll use 'any' to allow both values and functions
|
|
1074
|
+
const scope = {
|
|
1075
|
+
// Direct access to workflow data
|
|
1076
|
+
inputs: workflowData.inputs,
|
|
1077
|
+
variables: workflowData.variables,
|
|
1078
|
+
vars: workflowData.vars,
|
|
1079
|
+
outputs: workflowData.outputs,
|
|
1080
|
+
// Context object with eval function (similar to entity-detail-list pattern)
|
|
1081
|
+
context: {
|
|
1082
|
+
eval: (path) => {
|
|
1083
|
+
// Use lodash get to access nested properties
|
|
1084
|
+
// Supports paths like: "inputs.userName", "variables.count", "outputs.activityId.property"
|
|
1085
|
+
return get(workflowData, path);
|
|
1086
|
+
},
|
|
1087
|
+
},
|
|
1088
|
+
};
|
|
1089
|
+
return scope;
|
|
1090
|
+
}
|
|
1091
|
+
/**
|
|
1092
|
+
* Build expression evaluation scope from workflow instance state.
|
|
1093
|
+
*
|
|
1094
|
+
* Convenience method that extracts data from AXPWorkflowInstanceState.
|
|
1095
|
+
*
|
|
1096
|
+
* @param state - Workflow instance state
|
|
1097
|
+
* @param activityOutputs - Map of activity outputs (activityId -> output)
|
|
1098
|
+
* @returns Expression evaluator scope with workflow data and context.eval() function
|
|
1099
|
+
*/
|
|
1100
|
+
buildScopeFromState(state, activityOutputs) {
|
|
1101
|
+
// Convert activity outputs to record format
|
|
1102
|
+
const outputs = {};
|
|
1103
|
+
if (activityOutputs) {
|
|
1104
|
+
if (activityOutputs instanceof Map) {
|
|
1105
|
+
activityOutputs.forEach((output, activityId) => {
|
|
1106
|
+
outputs[activityId] = output;
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
1109
|
+
else {
|
|
1110
|
+
Object.assign(outputs, activityOutputs);
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
// Convenience alias for the last activity output (if available).
|
|
1114
|
+
// This allows expressions like: {{outputs.last.someField}}
|
|
1115
|
+
if (outputs['last'] === undefined && state.lastActivityOutput !== undefined) {
|
|
1116
|
+
outputs['last'] = state.lastActivityOutput;
|
|
1117
|
+
}
|
|
1118
|
+
return this.buildScope({
|
|
1119
|
+
inputs: this.normalizeInputs((state.input || {})),
|
|
1120
|
+
variables: state.variables || {},
|
|
1121
|
+
outputs: outputs,
|
|
1122
|
+
});
|
|
1123
|
+
}
|
|
1124
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: WorkflowExpressionScopeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1125
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: WorkflowExpressionScopeService, providedIn: 'root' }); }
|
|
1126
|
+
}
|
|
1127
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: WorkflowExpressionScopeService, decorators: [{
|
|
1128
|
+
type: Injectable,
|
|
1129
|
+
args: [{
|
|
1130
|
+
providedIn: 'root'
|
|
1131
|
+
}]
|
|
1132
|
+
}] });
|
|
1133
|
+
|
|
1134
|
+
//#region ---- Constants ----
|
|
1135
|
+
/**
|
|
1136
|
+
* Activity types handled internally by the workflow engine (e.g. mock backend).
|
|
1137
|
+
* When such an activity is not registered as Command on the client, we skip execution
|
|
1138
|
+
* without warning — the engine will run it when executing the workflow.
|
|
1139
|
+
*/
|
|
1140
|
+
const ENGINE_BUILTIN_ACTIVITY_TYPES = new Set([
|
|
1141
|
+
'workflow-activity:set-variable',
|
|
1142
|
+
'workflow-activity:http-request',
|
|
1143
|
+
'workflow-activity:resolve-employee-user-id',
|
|
1144
|
+
]);
|
|
861
1145
|
//#endregion
|
|
862
1146
|
/**
|
|
863
|
-
*
|
|
1147
|
+
* Activity Executor Service
|
|
1148
|
+
*
|
|
1149
|
+
* Service for executing workflow activities via CommandBus.
|
|
1150
|
+
* Automatically evaluates expressions in activity inputs before execution.
|
|
864
1151
|
*
|
|
865
|
-
*
|
|
866
|
-
*
|
|
867
|
-
*
|
|
1152
|
+
* @example
|
|
1153
|
+
* ```typescript
|
|
1154
|
+
* const executor = inject(ActivityExecutor);
|
|
868
1155
|
*
|
|
869
|
-
*
|
|
1156
|
+
* // Execute activity with task and workflow state (expressions will be evaluated)
|
|
1157
|
+
* const result = await executor.execute(task, workflowState, activityOutputs);
|
|
1158
|
+
* ```
|
|
870
1159
|
*/
|
|
871
|
-
class
|
|
1160
|
+
class ActivityExecutor {
|
|
872
1161
|
constructor() {
|
|
873
1162
|
//#region ---- Services & Dependencies ----
|
|
874
1163
|
this.commandService = inject(AXPCommandService);
|
|
1164
|
+
this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
|
|
1165
|
+
this.expressionScopeService = inject(WorkflowExpressionScopeService);
|
|
1166
|
+
this.translateService = inject(AXTranslationService);
|
|
875
1167
|
}
|
|
876
1168
|
//#endregion
|
|
877
1169
|
//#region ---- Public Methods ----
|
|
878
1170
|
/**
|
|
879
|
-
* Execute a
|
|
1171
|
+
* Execute a workflow activity with expression evaluation.
|
|
880
1172
|
*
|
|
881
|
-
*
|
|
882
|
-
*
|
|
1173
|
+
* Evaluates expressions in activity inputs using workflow state,
|
|
1174
|
+
* then executes the activity via CommandBus.
|
|
883
1175
|
*
|
|
884
|
-
* @param task -
|
|
1176
|
+
* @param task - Workflow task containing activity information
|
|
1177
|
+
* @param workflowState - Current workflow instance state (for expression evaluation)
|
|
1178
|
+
* @param activityOutputs - Map of previous activity outputs (for expression evaluation)
|
|
885
1179
|
* @returns Execution result with output and outcome
|
|
886
|
-
*
|
|
887
|
-
* @throws Error if task is not a frontend task
|
|
888
1180
|
*/
|
|
889
|
-
async execute(task) {
|
|
890
|
-
// Validate execution mode
|
|
891
|
-
if (task.executionMode !== 'frontend' && task.executionMode !== 'both') {
|
|
892
|
-
throw new Error(`Task '${task.activityId}' is not a frontend task. ` +
|
|
893
|
-
`Execution mode: ${task.executionMode}. Backend tasks are handled automatically.`);
|
|
894
|
-
}
|
|
1181
|
+
async execute(task, workflowState, activityOutputs) {
|
|
895
1182
|
try {
|
|
1183
|
+
const activityName = task.activityType;
|
|
1184
|
+
// Evaluate inputs if workflow state is provided
|
|
1185
|
+
let evaluatedInputs = task.input || {};
|
|
1186
|
+
if (workflowState) {
|
|
1187
|
+
// Prefer explicit outputs, fallback to outputs stored in state
|
|
1188
|
+
const outputsForScope = activityOutputs ??
|
|
1189
|
+
workflowState.activityOutputs ??
|
|
1190
|
+
undefined;
|
|
1191
|
+
// Build expression scope from workflow state
|
|
1192
|
+
const scope = this.expressionScopeService.buildScopeFromState(workflowState, outputsForScope);
|
|
1193
|
+
// Evaluate all inputs recursively (handles nested objects and arrays)
|
|
1194
|
+
evaluatedInputs = await this.expressionEvaluator.evaluate(task.input || {}, scope);
|
|
1195
|
+
}
|
|
896
1196
|
// Check if command exists
|
|
897
|
-
const commandExists = this.commandService.exists(
|
|
1197
|
+
const commandExists = this.commandService.exists(activityName);
|
|
898
1198
|
if (!commandExists) {
|
|
899
|
-
|
|
900
|
-
`
|
|
1199
|
+
if (!ENGINE_BUILTIN_ACTIVITY_TYPES.has(activityName)) {
|
|
1200
|
+
console.warn(`[ActivityExecutor] ⚠️ Activity '${activityName}' is not registered as Command. ` +
|
|
1201
|
+
`Skipping execution.`);
|
|
1202
|
+
}
|
|
901
1203
|
return {
|
|
902
1204
|
output: null,
|
|
903
1205
|
outcome: 'Done'
|
|
904
1206
|
};
|
|
905
1207
|
}
|
|
906
|
-
//
|
|
907
|
-
|
|
908
|
-
let commandInput = task.input || task.config || {};
|
|
1208
|
+
// Flatten properties if nested (designer-style nested payload)
|
|
1209
|
+
let commandInput = evaluatedInputs;
|
|
909
1210
|
if (commandInput['properties'] && typeof commandInput['properties'] === 'object') {
|
|
910
1211
|
// Flatten: {properties: {text: "..."}} -> {text: "..."}
|
|
911
1212
|
commandInput = { ...commandInput['properties'] };
|
|
912
1213
|
}
|
|
913
1214
|
// Execute activity via CommandBus
|
|
914
|
-
// Activities
|
|
915
|
-
const result = await this.commandService.execute(
|
|
1215
|
+
// Activities (AXPActivity) return {output, outcome}; legacy may return {output, outcomes}
|
|
1216
|
+
const result = await this.commandService.execute(activityName, commandInput);
|
|
916
1217
|
if (!result) {
|
|
917
1218
|
return {
|
|
918
1219
|
output: null,
|
|
@@ -922,42 +1223,151 @@ class FrontendTaskExecutor {
|
|
|
922
1223
|
if (!result.success) {
|
|
923
1224
|
return {
|
|
924
1225
|
output: {
|
|
925
|
-
error: result.message?.text,
|
|
1226
|
+
error: await this.resolveCommandMessageTextForError(result.message?.text),
|
|
926
1227
|
},
|
|
927
1228
|
outcome: 'Failed',
|
|
928
1229
|
};
|
|
929
1230
|
}
|
|
930
1231
|
const commandResult = result.data;
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
// Default to 'Done' if no outcomes specified
|
|
1232
|
+
// Prefer unified outcome in result.metadata; fall back to legacy data.outcome/outcomes.
|
|
1233
|
+
const metadataOutcome = result?.metadata?.['outcome'];
|
|
934
1234
|
let outcome = 'Done';
|
|
935
|
-
if (
|
|
936
|
-
outcome =
|
|
1235
|
+
if (typeof metadataOutcome === 'string' && metadataOutcome.length > 0) {
|
|
1236
|
+
outcome = metadataOutcome;
|
|
937
1237
|
}
|
|
1238
|
+
else if (typeof commandResult?.outcome === 'string' && commandResult.outcome.length > 0) {
|
|
1239
|
+
outcome = commandResult.outcome;
|
|
1240
|
+
}
|
|
1241
|
+
else {
|
|
1242
|
+
const outcomes = (commandResult?.outcomes ?? {});
|
|
1243
|
+
if (outcomes && typeof outcomes === 'object' && Object.keys(outcomes).length > 0) {
|
|
1244
|
+
outcome = outcomes['Done'] ? 'Done' : Object.keys(outcomes)[0] || 'Done';
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
// Prefer output wrapper when present; otherwise treat data itself as output.
|
|
1248
|
+
const output = commandResult && typeof commandResult === 'object' && 'output' in commandResult
|
|
1249
|
+
? commandResult.output
|
|
1250
|
+
: commandResult;
|
|
938
1251
|
return {
|
|
939
|
-
output:
|
|
1252
|
+
output: output ?? null,
|
|
940
1253
|
outcome,
|
|
941
1254
|
};
|
|
942
1255
|
}
|
|
943
1256
|
catch (error) {
|
|
944
|
-
console.error(`[
|
|
1257
|
+
console.error(`[ActivityExecutor] ❌ Error evaluating expressions or executing activity:`, error);
|
|
945
1258
|
return {
|
|
946
1259
|
output: { error: error.message || 'Unknown error' },
|
|
947
1260
|
outcome: 'Failed'
|
|
948
1261
|
};
|
|
949
1262
|
}
|
|
950
1263
|
}
|
|
951
|
-
|
|
952
|
-
|
|
1264
|
+
/**
|
|
1265
|
+
* Resolves command failure message text for workflow output: `@` keys via translate, MLS maps via resolve.
|
|
1266
|
+
*/
|
|
1267
|
+
async resolveCommandMessageTextForError(value) {
|
|
1268
|
+
if (value == null) {
|
|
1269
|
+
return '';
|
|
1270
|
+
}
|
|
1271
|
+
if (typeof value === 'string') {
|
|
1272
|
+
return value.startsWith('@') ? await this.translateService.translateAsync(value) : value;
|
|
1273
|
+
}
|
|
1274
|
+
return this.translateService.resolve(value);
|
|
1275
|
+
}
|
|
1276
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ActivityExecutor, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1277
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ActivityExecutor, providedIn: 'root' }); }
|
|
953
1278
|
}
|
|
954
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1279
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ActivityExecutor, decorators: [{
|
|
955
1280
|
type: Injectable,
|
|
956
1281
|
args: [{
|
|
957
1282
|
providedIn: 'root'
|
|
958
1283
|
}]
|
|
959
1284
|
}] });
|
|
960
1285
|
|
|
1286
|
+
const AXP_WORKFLOW_CONTINUATION_HOOK = new InjectionToken('AXP_WORKFLOW_CONTINUATION_HOOK');
|
|
1287
|
+
/** When true on resume `userInput`, skips the post-step continuation dialog (auto-advance). */
|
|
1288
|
+
const AXP_WORKFLOW_SUPPRESS_CONTINUATION_INPUT_KEY = '_suppressWorkflowContinuation';
|
|
1289
|
+
function isWorkflowContinuationSuppressed(userInput) {
|
|
1290
|
+
if (userInput == null || typeof userInput !== 'object') {
|
|
1291
|
+
return false;
|
|
1292
|
+
}
|
|
1293
|
+
return userInput[AXP_WORKFLOW_SUPPRESS_CONTINUATION_INPUT_KEY] === true;
|
|
1294
|
+
}
|
|
1295
|
+
//#endregion
|
|
1296
|
+
|
|
1297
|
+
//#region ---- Inline frontend classification ----
|
|
1298
|
+
/**
|
|
1299
|
+
* Frontend step executed inline (dialog/popup), not suspended on the task board.
|
|
1300
|
+
* Derived from execution mode and task-board activity types — no per-activity hardcoding.
|
|
1301
|
+
*/
|
|
1302
|
+
function axpIsWorkflowInlineFrontendTask(task) {
|
|
1303
|
+
if (!task) {
|
|
1304
|
+
return false;
|
|
1305
|
+
}
|
|
1306
|
+
if (axpIsWorkflowTaskBoardActivityType(task.activityType)) {
|
|
1307
|
+
return false;
|
|
1308
|
+
}
|
|
1309
|
+
return task.executionMode === 'frontend' || task.executionMode === 'both';
|
|
1310
|
+
}
|
|
1311
|
+
/** @deprecated Use {@link axpIsWorkflowInlineFrontendTask}. */
|
|
1312
|
+
function axpIsWorkflowInteractiveFrontendTask(task) {
|
|
1313
|
+
return axpIsWorkflowInlineFrontendTask(task);
|
|
1314
|
+
}
|
|
1315
|
+
//#endregion
|
|
1316
|
+
//#region ---- Continuation metadata on tasks ----
|
|
1317
|
+
/** Resolved before-interactive behavior from task metadata (set by engine from activity definition). */
|
|
1318
|
+
function axpResolveWorkflowContinuationBeforeInteractive(task) {
|
|
1319
|
+
return task?.continuation?.beforeInteractive ?? 'default';
|
|
1320
|
+
}
|
|
1321
|
+
/**
|
|
1322
|
+
* Whether to skip the pre-interactive "continue?" prompt based on activity metadata.
|
|
1323
|
+
* Assignee-specific rules are applied in workflow-management (needs session).
|
|
1324
|
+
*/
|
|
1325
|
+
function axpShouldSkipBeforeInteractiveFromMetadata(behavior, completedWasHumanTask) {
|
|
1326
|
+
return behavior === 'skip-when-chained-from-human-task' && completedWasHumanTask;
|
|
1327
|
+
}
|
|
1328
|
+
/**
|
|
1329
|
+
* Whether to show a "continue?" prompt before running inline frontend activities.
|
|
1330
|
+
* Skips when the user already resumed a task-board step (primary action / resume).
|
|
1331
|
+
*/
|
|
1332
|
+
function axpShouldOfferBeforeInteractiveFlow(context) {
|
|
1333
|
+
return !context.completedActivityId;
|
|
1334
|
+
}
|
|
1335
|
+
//#endregion
|
|
1336
|
+
//#region ---- Step advancement gate ----
|
|
1337
|
+
/** Resume outcomes that do not advance the workflow graph (draft save, cancel, loop back). */
|
|
1338
|
+
const NON_ADVANCING_RESUME_OUTCOMES = new Set(['saved', 'cancelled', 'cancel', 'save', 'draft']);
|
|
1339
|
+
/**
|
|
1340
|
+
* Whether the workflow advanced enough to consider a continuation prompt.
|
|
1341
|
+
* Includes pending interactive steps when inbox bookmarks are already consumed.
|
|
1342
|
+
*/
|
|
1343
|
+
function axpShouldOfferWorkflowContinuationAfterStep(context, activeBookmarkActivityIds) {
|
|
1344
|
+
const outcome = context.resumeOutcome?.trim().toLowerCase();
|
|
1345
|
+
if (outcome && NON_ADVANCING_RESUME_OUTCOMES.has(outcome)) {
|
|
1346
|
+
return false;
|
|
1347
|
+
}
|
|
1348
|
+
const pendingActivityId = context.pendingNextTask?.activityId;
|
|
1349
|
+
const completedActivityId = context.completedActivityId;
|
|
1350
|
+
if (pendingActivityId && completedActivityId && pendingActivityId === completedActivityId) {
|
|
1351
|
+
return false;
|
|
1352
|
+
}
|
|
1353
|
+
if (activeBookmarkActivityIds.length === 0) {
|
|
1354
|
+
const pending = context.pendingNextTask;
|
|
1355
|
+
if (completedActivityId && pending && pending.activityId !== completedActivityId) {
|
|
1356
|
+
if (axpIsWorkflowInlineFrontendTask(pending) ||
|
|
1357
|
+
axpIsWorkflowTaskBoardActivityType(pending.activityType)) {
|
|
1358
|
+
return true;
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
return false;
|
|
1362
|
+
}
|
|
1363
|
+
/** No continuation on bare workflow start (bookmarks exist before any step completes). */
|
|
1364
|
+
if (!completedActivityId) {
|
|
1365
|
+
return false;
|
|
1366
|
+
}
|
|
1367
|
+
return activeBookmarkActivityIds.some((id) => id !== completedActivityId);
|
|
1368
|
+
}
|
|
1369
|
+
//#endregion
|
|
1370
|
+
|
|
961
1371
|
//#endregion
|
|
962
1372
|
/**
|
|
963
1373
|
* Workflow Manager - Facade for workflow lifecycle orchestration.
|
|
@@ -967,13 +1377,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
967
1377
|
*
|
|
968
1378
|
* Responsibilities:
|
|
969
1379
|
* - Orchestrate workflow lifecycle (start, execute, complete, resume)
|
|
970
|
-
* - Delegate execution to
|
|
1380
|
+
* - Delegate execution to ActivityExecutor
|
|
971
1381
|
* - Cache workflow state in memory
|
|
972
1382
|
* - Expose a stable API for UI
|
|
973
1383
|
*
|
|
974
1384
|
* Rules:
|
|
975
1385
|
* - No HTTP calls (delegates to AXPWorkflowEngine)
|
|
976
|
-
* - No CommandBus / Command execution (delegates to
|
|
1386
|
+
* - No CommandBus / Command execution (delegates to ActivityExecutor)
|
|
977
1387
|
* - No workflow branching logic (backend decides)
|
|
978
1388
|
* - No business validation (backend validates)
|
|
979
1389
|
* - No backend assumptions (uses abstract runtime service)
|
|
@@ -982,7 +1392,8 @@ class AXPWorkflowManager {
|
|
|
982
1392
|
constructor() {
|
|
983
1393
|
//#region ---- Services & Dependencies ----
|
|
984
1394
|
this.workflowEngine = inject(AXP_WORKFLOW_ENGINE);
|
|
985
|
-
this.
|
|
1395
|
+
this.activityExecutor = inject(ActivityExecutor);
|
|
1396
|
+
this.continuationHook = inject(AXP_WORKFLOW_CONTINUATION_HOOK, { optional: true });
|
|
986
1397
|
//#endregion
|
|
987
1398
|
//#region ---- State Cache ----
|
|
988
1399
|
/**
|
|
@@ -998,6 +1409,175 @@ class AXPWorkflowManager {
|
|
|
998
1409
|
}
|
|
999
1410
|
//#endregion
|
|
1000
1411
|
//#region ---- Public Methods ----
|
|
1412
|
+
/**
|
|
1413
|
+
* Execute frontend activities interactively until reaching workflow-activity:human-task or completion.
|
|
1414
|
+
*
|
|
1415
|
+
* Interactive = show form/popup immediately (user sees and acts). Only workflow-activity:human-task
|
|
1416
|
+
* is not interactive (goes to task board). Other frontend activities (show-layout-popup, show-toast, etc.)
|
|
1417
|
+
* even with taskType human-task in definition are executed here.
|
|
1418
|
+
*
|
|
1419
|
+
* @param instanceId - Workflow instance ID
|
|
1420
|
+
* @param task - Current task to execute
|
|
1421
|
+
* @param state - Current workflow state
|
|
1422
|
+
* @param lastActivityOutput - Last activity output (for expression evaluation)
|
|
1423
|
+
* @returns Final result with nextTask (if workflow-activity:human-task) or completion status
|
|
1424
|
+
*/
|
|
1425
|
+
async executeInteractiveFlow(instanceId, task, state, activityOutputs) {
|
|
1426
|
+
let currentTask = task;
|
|
1427
|
+
let currentState = state;
|
|
1428
|
+
let currentActivityOutputs = {
|
|
1429
|
+
...(currentState.activityOutputs || {}),
|
|
1430
|
+
...(activityOutputs || {}),
|
|
1431
|
+
};
|
|
1432
|
+
const maxIterations = 100; // Prevent infinite loops
|
|
1433
|
+
let iterationCount = 0;
|
|
1434
|
+
while (currentTask && iterationCount < maxIterations) {
|
|
1435
|
+
iterationCount++;
|
|
1436
|
+
// Interactive = frontend executionMode and NOT task-board activities (human-task, cartable)
|
|
1437
|
+
const isInteractive = (currentTask.executionMode === 'frontend' || currentTask.executionMode === 'both') &&
|
|
1438
|
+
!axpIsWorkflowTaskBoardActivityType(currentTask.activityType);
|
|
1439
|
+
if (isInteractive) {
|
|
1440
|
+
// Execute frontend activity
|
|
1441
|
+
const execResult = await this.activityExecutor.execute(currentTask, currentState, currentActivityOutputs);
|
|
1442
|
+
// Track outputs locally (backend should also persist and return them)
|
|
1443
|
+
currentActivityOutputs = {
|
|
1444
|
+
...currentActivityOutputs,
|
|
1445
|
+
[currentTask.activityId]: execResult.output,
|
|
1446
|
+
};
|
|
1447
|
+
// Send result to backend
|
|
1448
|
+
const completeResponse = await this.workflowEngine.frontActivtyComplete({
|
|
1449
|
+
instanceId,
|
|
1450
|
+
activityNode: currentTask.activityId,
|
|
1451
|
+
output: execResult.output || {},
|
|
1452
|
+
outcome: execResult.outcome,
|
|
1453
|
+
});
|
|
1454
|
+
// Update state cache
|
|
1455
|
+
if (completeResponse.state) {
|
|
1456
|
+
const normalizedState = { ...completeResponse.state };
|
|
1457
|
+
if (normalizedState.lastUpdated && !(normalizedState.lastUpdated instanceof Date)) {
|
|
1458
|
+
normalizedState.lastUpdated = new Date(normalizedState.lastUpdated);
|
|
1459
|
+
}
|
|
1460
|
+
currentState = normalizedState;
|
|
1461
|
+
// Prefer outputs returned by backend; fallback to local cache
|
|
1462
|
+
currentActivityOutputs = {
|
|
1463
|
+
...currentActivityOutputs,
|
|
1464
|
+
...(normalizedState.activityOutputs || {}),
|
|
1465
|
+
};
|
|
1466
|
+
this.stateCache.set(instanceId, normalizedState);
|
|
1467
|
+
}
|
|
1468
|
+
// Backend decides: if no nextTask, workflow is completed
|
|
1469
|
+
if (!completeResponse.nextTask) {
|
|
1470
|
+
return {
|
|
1471
|
+
nextTask: null,
|
|
1472
|
+
state: currentState,
|
|
1473
|
+
output: completeResponse.output,
|
|
1474
|
+
};
|
|
1475
|
+
}
|
|
1476
|
+
// Backend decides: if nextTask is task-board activity or not frontend, return it (task board or done)
|
|
1477
|
+
const nextInteractive = (completeResponse.nextTask.executionMode === 'frontend' || completeResponse.nextTask.executionMode === 'both') &&
|
|
1478
|
+
!axpIsWorkflowTaskBoardActivityType(completeResponse.nextTask.activityType);
|
|
1479
|
+
if (!nextInteractive) {
|
|
1480
|
+
const humanTaskNext = completeResponse.nextTask;
|
|
1481
|
+
let boundaryContinuationOffer;
|
|
1482
|
+
if (humanTaskNext &&
|
|
1483
|
+
axpIsWorkflowTaskBoardActivityType(humanTaskNext.activityType)) {
|
|
1484
|
+
boundaryContinuationOffer =
|
|
1485
|
+
(await this.continuationHook?.offerAfterWorkflowStep?.({
|
|
1486
|
+
instanceId,
|
|
1487
|
+
completedActivityId: currentTask.activityId,
|
|
1488
|
+
resumeOutcome: execResult.outcome,
|
|
1489
|
+
pendingNextTask: humanTaskNext,
|
|
1490
|
+
})) ?? 'not-offered';
|
|
1491
|
+
}
|
|
1492
|
+
return {
|
|
1493
|
+
nextTask: humanTaskNext,
|
|
1494
|
+
state: currentState,
|
|
1495
|
+
boundaryContinuationOffer,
|
|
1496
|
+
};
|
|
1497
|
+
}
|
|
1498
|
+
// Continue with next interactive frontend task
|
|
1499
|
+
currentTask = completeResponse.nextTask;
|
|
1500
|
+
}
|
|
1501
|
+
else {
|
|
1502
|
+
// Not interactive (e.g. human-task / cartable) - return as-is for task board
|
|
1503
|
+
return {
|
|
1504
|
+
nextTask: currentTask,
|
|
1505
|
+
state: currentState,
|
|
1506
|
+
};
|
|
1507
|
+
}
|
|
1508
|
+
}
|
|
1509
|
+
// Max iterations reached
|
|
1510
|
+
if (iterationCount >= maxIterations) {
|
|
1511
|
+
console.warn(`[AXPWorkflowManager] ⚠️ Maximum iterations (${maxIterations}) reached`);
|
|
1512
|
+
}
|
|
1513
|
+
return {
|
|
1514
|
+
nextTask: currentTask,
|
|
1515
|
+
state: currentState,
|
|
1516
|
+
};
|
|
1517
|
+
}
|
|
1518
|
+
/**
|
|
1519
|
+
* Runs inline interactive activities when allowed, with an optional pre-flow continuation prompt.
|
|
1520
|
+
*/
|
|
1521
|
+
async runInteractiveFlowWithContinuation(instanceId, pendingTask, state, continuationContext, suppressContinuation, activityOutputs) {
|
|
1522
|
+
let continuationOffer = 'not-offered';
|
|
1523
|
+
if (!suppressContinuation &&
|
|
1524
|
+
axpShouldOfferBeforeInteractiveFlow(continuationContext) &&
|
|
1525
|
+
axpIsWorkflowInlineFrontendTask(pendingTask) &&
|
|
1526
|
+
this.continuationHook?.offerBeforeInteractiveFlow) {
|
|
1527
|
+
continuationOffer =
|
|
1528
|
+
(await this.continuationHook.offerBeforeInteractiveFlow({
|
|
1529
|
+
...continuationContext,
|
|
1530
|
+
instanceId,
|
|
1531
|
+
pendingNextTask: pendingTask,
|
|
1532
|
+
})) ?? 'not-offered';
|
|
1533
|
+
if (continuationOffer === 'declined') {
|
|
1534
|
+
await this.revertResumeAfterDeclinedInteractiveContinuation(instanceId, continuationContext, pendingTask);
|
|
1535
|
+
const revertedState = this.stateCache.get(instanceId) ?? state;
|
|
1536
|
+
return { nextTask: null, state: revertedState, continuationOffer };
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
const interactiveResult = await this.executeInteractiveFlow(instanceId, pendingTask, state, activityOutputs);
|
|
1540
|
+
const boundaryOffer = interactiveResult.boundaryContinuationOffer;
|
|
1541
|
+
if (boundaryOffer && boundaryOffer !== 'not-offered') {
|
|
1542
|
+
continuationOffer = boundaryOffer;
|
|
1543
|
+
}
|
|
1544
|
+
return { ...interactiveResult, continuationOffer };
|
|
1545
|
+
}
|
|
1546
|
+
async invokeWorkflowContinuationAfterStep(context, priorOffer, suppressContinuation = false) {
|
|
1547
|
+
if (suppressContinuation || priorOffer === 'declined') {
|
|
1548
|
+
return;
|
|
1549
|
+
}
|
|
1550
|
+
if (priorOffer && priorOffer !== 'not-offered') {
|
|
1551
|
+
return;
|
|
1552
|
+
}
|
|
1553
|
+
await this.continuationHook?.offerAfterWorkflowStep?.(context);
|
|
1554
|
+
}
|
|
1555
|
+
/**
|
|
1556
|
+
* Restores the suspended task-board step when the user declines a pre-interactive continuation prompt.
|
|
1557
|
+
*/
|
|
1558
|
+
async revertResumeAfterDeclinedInteractiveContinuation(instanceId, context, abortedTask) {
|
|
1559
|
+
const suspendedStepId = context.completedActivityId;
|
|
1560
|
+
if (!suspendedStepId) {
|
|
1561
|
+
return;
|
|
1562
|
+
}
|
|
1563
|
+
const revert = this.workflowEngine.revertResumeAfterDeclinedInteractiveContinuation?.bind(this.workflowEngine);
|
|
1564
|
+
if (!revert) {
|
|
1565
|
+
return;
|
|
1566
|
+
}
|
|
1567
|
+
const result = await revert({
|
|
1568
|
+
instanceId,
|
|
1569
|
+
suspendedStepId,
|
|
1570
|
+
abortedStepId: abortedTask.activityId,
|
|
1571
|
+
bookmarkId: context.completedBookmarkId,
|
|
1572
|
+
});
|
|
1573
|
+
if (result.success && result.state) {
|
|
1574
|
+
let normalizedState = { ...result.state };
|
|
1575
|
+
if (normalizedState.lastUpdated && !(normalizedState.lastUpdated instanceof Date)) {
|
|
1576
|
+
normalizedState.lastUpdated = new Date(normalizedState.lastUpdated);
|
|
1577
|
+
}
|
|
1578
|
+
this.stateCache.set(instanceId, normalizedState);
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1001
1581
|
/**
|
|
1002
1582
|
* Start a new workflow instance.
|
|
1003
1583
|
*
|
|
@@ -1025,90 +1605,44 @@ class AXPWorkflowManager {
|
|
|
1025
1605
|
try {
|
|
1026
1606
|
const response = await this.workflowEngine.start({
|
|
1027
1607
|
workflowId,
|
|
1028
|
-
input
|
|
1608
|
+
input,
|
|
1029
1609
|
});
|
|
1030
1610
|
// Cache state (normalize Date)
|
|
1031
|
-
|
|
1611
|
+
let startNormalizedState = { ...response.state };
|
|
1032
1612
|
if (startNormalizedState.lastUpdated && !(startNormalizedState.lastUpdated instanceof Date)) {
|
|
1033
1613
|
startNormalizedState.lastUpdated = new Date(startNormalizedState.lastUpdated);
|
|
1034
1614
|
}
|
|
1035
1615
|
this.stateCache.set(response.instanceId, startNormalizedState);
|
|
1616
|
+
// 🎯 Interactive flow: Execute frontend activities that are NOT task-board types (those go to task board)
|
|
1617
|
+
let finalNextTask = response.pendingTask || null;
|
|
1618
|
+
let finalOutput = startNormalizedState.output;
|
|
1619
|
+
const pendingTask = response.pendingTask;
|
|
1620
|
+
if (pendingTask &&
|
|
1621
|
+
(pendingTask.executionMode === 'frontend' || pendingTask.executionMode === 'both') &&
|
|
1622
|
+
!axpIsWorkflowTaskBoardActivityType(pendingTask.activityType)) {
|
|
1623
|
+
const interactiveResult = await this.runInteractiveFlowWithContinuation(response.instanceId, pendingTask, startNormalizedState, { instanceId: response.instanceId, pendingNextTask: pendingTask }, isWorkflowContinuationSuppressed(input), (response.activityOutputs ?? response.state.activityOutputs));
|
|
1624
|
+
finalNextTask = interactiveResult.nextTask;
|
|
1625
|
+
startNormalizedState = interactiveResult.state;
|
|
1626
|
+
if (interactiveResult.output != null) {
|
|
1627
|
+
finalOutput = interactiveResult.output;
|
|
1628
|
+
}
|
|
1629
|
+
this.stateCache.set(response.instanceId, startNormalizedState);
|
|
1630
|
+
}
|
|
1631
|
+
// If backend returned null or non-executable task, return it as-is
|
|
1632
|
+
// Backend already decided workflow status (suspended, completed, etc.)
|
|
1036
1633
|
return {
|
|
1037
1634
|
success: true,
|
|
1038
1635
|
instanceId: response.instanceId,
|
|
1039
1636
|
state: startNormalizedState,
|
|
1040
|
-
nextTask:
|
|
1041
|
-
output:
|
|
1637
|
+
nextTask: finalNextTask,
|
|
1638
|
+
output: finalOutput,
|
|
1042
1639
|
};
|
|
1043
1640
|
}
|
|
1044
1641
|
catch (error) {
|
|
1045
1642
|
console.error('[AXPWorkflowManager] ❌ Error starting workflow:', error);
|
|
1046
1643
|
return {
|
|
1047
1644
|
success: false,
|
|
1048
|
-
error: error.message || 'Failed to start workflow'
|
|
1049
|
-
};
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
/**
|
|
1053
|
-
* Execute a frontend task.
|
|
1054
|
-
*
|
|
1055
|
-
* Delegates to FrontendTaskExecutor for actual execution.
|
|
1056
|
-
* Only executes tasks with executionMode 'frontend' or 'both'.
|
|
1057
|
-
*
|
|
1058
|
-
* @param task - Task to execute
|
|
1059
|
-
* @returns Execution result with output and outcome
|
|
1060
|
-
*
|
|
1061
|
-
* @throws Error if task is not a frontend task
|
|
1062
|
-
*/
|
|
1063
|
-
async execute(task) {
|
|
1064
|
-
return this.frontendTaskExecutor.execute(task);
|
|
1065
|
-
}
|
|
1066
|
-
/**
|
|
1067
|
-
* Complete a task and get next task from backend.
|
|
1068
|
-
*
|
|
1069
|
-
* Sends task result to backend API.
|
|
1070
|
-
* Backend decides: next task, fail, or complete workflow.
|
|
1071
|
-
*
|
|
1072
|
-
* @param instanceId - Workflow instance ID
|
|
1073
|
-
* @param task - Completed task
|
|
1074
|
-
* @param outcome - Task outcome (e.g., 'Done', 'Confirmed', 'Cancelled')
|
|
1075
|
-
* @param output - Task output/result (optional)
|
|
1076
|
-
* @returns Complete result with next task (if any)
|
|
1077
|
-
*/
|
|
1078
|
-
async complete(instanceId, task, outcome, output) {
|
|
1079
|
-
try {
|
|
1080
|
-
// Send result to backend - backend decides next step
|
|
1081
|
-
const response = await this.workflowEngine.resume({
|
|
1082
|
-
instanceId,
|
|
1083
|
-
stepId: task.activityId,
|
|
1084
|
-
taskToken: task.taskToken,
|
|
1085
|
-
outcome,
|
|
1086
|
-
userInput: output
|
|
1087
|
-
});
|
|
1088
|
-
// Update cache
|
|
1089
|
-
let completeNormalizedState = response.state;
|
|
1090
|
-
if (response.state) {
|
|
1091
|
-
// Normalize lastUpdated to Date (for cache safety)
|
|
1092
|
-
completeNormalizedState = { ...response.state };
|
|
1093
|
-
if (completeNormalizedState.lastUpdated && !(completeNormalizedState.lastUpdated instanceof Date)) {
|
|
1094
|
-
completeNormalizedState.lastUpdated = new Date(completeNormalizedState.lastUpdated);
|
|
1095
|
-
}
|
|
1096
|
-
this.stateCache.set(instanceId, completeNormalizedState);
|
|
1097
|
-
}
|
|
1098
|
-
return {
|
|
1099
|
-
success: true,
|
|
1100
|
-
instanceId,
|
|
1101
|
-
state: completeNormalizedState,
|
|
1102
|
-
nextTask: response.nextTask || null,
|
|
1103
|
-
output: response.output
|
|
1104
|
-
};
|
|
1105
|
-
}
|
|
1106
|
-
catch (error) {
|
|
1107
|
-
console.error('[AXPWorkflowManager] ❌ Error completing task:', error);
|
|
1108
|
-
return {
|
|
1109
|
-
success: false,
|
|
1110
|
-
instanceId,
|
|
1111
|
-
error: error.message || 'Failed to complete task'
|
|
1645
|
+
error: error.message || 'Failed to start workflow',
|
|
1112
1646
|
};
|
|
1113
1647
|
}
|
|
1114
1648
|
}
|
|
@@ -1137,36 +1671,70 @@ class AXPWorkflowManager {
|
|
|
1137
1671
|
stepId,
|
|
1138
1672
|
taskToken,
|
|
1139
1673
|
outcome,
|
|
1140
|
-
userInput
|
|
1674
|
+
userInput,
|
|
1141
1675
|
});
|
|
1142
1676
|
// Update cache with state from backend
|
|
1143
|
-
|
|
1144
|
-
// Normalize lastUpdated to Date (for cache safety)
|
|
1145
|
-
const normalizedState = { ...response.state };
|
|
1146
|
-
if (normalizedState.lastUpdated && !(normalizedState.lastUpdated instanceof Date)) {
|
|
1147
|
-
normalizedState.lastUpdated = new Date(normalizedState.lastUpdated);
|
|
1148
|
-
}
|
|
1149
|
-
this.stateCache.set(instanceId, normalizedState);
|
|
1150
|
-
}
|
|
1151
|
-
// Normalize state Date for return
|
|
1152
|
-
const normalizedState = response.state ? { ...response.state } : undefined;
|
|
1677
|
+
let normalizedState = response.state ? { ...response.state } : undefined;
|
|
1153
1678
|
if (normalizedState && normalizedState.lastUpdated && !(normalizedState.lastUpdated instanceof Date)) {
|
|
1154
1679
|
normalizedState.lastUpdated = new Date(normalizedState.lastUpdated);
|
|
1155
1680
|
}
|
|
1156
|
-
|
|
1681
|
+
if (normalizedState) {
|
|
1682
|
+
this.stateCache.set(instanceId, normalizedState);
|
|
1683
|
+
}
|
|
1684
|
+
// 🎯 Interactive flow: Execute frontend activities that are NOT task-board types (those go to task board)
|
|
1685
|
+
let finalNextTask = response.nextTask || null;
|
|
1686
|
+
let finalOutput = response.output;
|
|
1687
|
+
const nextTask = response.nextTask;
|
|
1688
|
+
let resumeContinuationOffer;
|
|
1689
|
+
if (nextTask &&
|
|
1690
|
+
(nextTask.executionMode === 'frontend' || nextTask.executionMode === 'both') &&
|
|
1691
|
+
!axpIsWorkflowTaskBoardActivityType(nextTask.activityType)) {
|
|
1692
|
+
const completedBookmarkId = typeof userInput === 'object' && userInput != null && 'bookmarkId' in userInput
|
|
1693
|
+
? String(userInput.bookmarkId ?? '')
|
|
1694
|
+
: undefined;
|
|
1695
|
+
const interactiveResult = await this.runInteractiveFlowWithContinuation(instanceId, nextTask, normalizedState, {
|
|
1696
|
+
instanceId,
|
|
1697
|
+
completedActivityId: stepId,
|
|
1698
|
+
completedBookmarkId: completedBookmarkId || undefined,
|
|
1699
|
+
resumeOutcome: outcome,
|
|
1700
|
+
pendingNextTask: nextTask,
|
|
1701
|
+
}, isWorkflowContinuationSuppressed(userInput), normalizedState?.activityOutputs);
|
|
1702
|
+
finalNextTask = interactiveResult.nextTask;
|
|
1703
|
+
normalizedState = interactiveResult.state;
|
|
1704
|
+
resumeContinuationOffer = interactiveResult.continuationOffer;
|
|
1705
|
+
if (interactiveResult.output != null) {
|
|
1706
|
+
finalOutput = interactiveResult.output;
|
|
1707
|
+
}
|
|
1708
|
+
this.stateCache.set(instanceId, normalizedState);
|
|
1709
|
+
}
|
|
1710
|
+
// If backend returned null or non-executable task, return it as-is
|
|
1711
|
+
// Backend already decided workflow status (suspended, completed, etc.)
|
|
1712
|
+
const resumeResult = {
|
|
1157
1713
|
success: true,
|
|
1158
1714
|
instanceId,
|
|
1159
1715
|
state: normalizedState || response.state,
|
|
1160
|
-
nextTask:
|
|
1161
|
-
output:
|
|
1716
|
+
nextTask: finalNextTask,
|
|
1717
|
+
output: finalOutput,
|
|
1162
1718
|
};
|
|
1719
|
+
const completedBookmarkIdForContinuation = typeof userInput === 'object' && userInput != null && 'bookmarkId' in userInput
|
|
1720
|
+
? String(userInput.bookmarkId ?? '')
|
|
1721
|
+
: undefined;
|
|
1722
|
+
await this.invokeWorkflowContinuationAfterStep({
|
|
1723
|
+
instanceId,
|
|
1724
|
+
completedActivityId: stepId,
|
|
1725
|
+
completedBookmarkId: completedBookmarkIdForContinuation || undefined,
|
|
1726
|
+
resumeOutcome: outcome,
|
|
1727
|
+
pendingNextTask: finalNextTask,
|
|
1728
|
+
}, resumeContinuationOffer, isWorkflowContinuationSuppressed(userInput));
|
|
1729
|
+
return resumeResult;
|
|
1163
1730
|
}
|
|
1164
1731
|
catch (error) {
|
|
1165
|
-
|
|
1732
|
+
const { message, code } = getWorkflowEngineErrorInfo(error);
|
|
1166
1733
|
return {
|
|
1167
1734
|
success: false,
|
|
1168
1735
|
instanceId,
|
|
1169
|
-
error:
|
|
1736
|
+
error: message,
|
|
1737
|
+
errorCode: code,
|
|
1170
1738
|
};
|
|
1171
1739
|
}
|
|
1172
1740
|
}
|
|
@@ -1196,7 +1764,7 @@ class AXPWorkflowManager {
|
|
|
1196
1764
|
// Fetch from backend
|
|
1197
1765
|
try {
|
|
1198
1766
|
const state = await this.workflowEngine.getState({
|
|
1199
|
-
instanceId
|
|
1767
|
+
instanceId,
|
|
1200
1768
|
});
|
|
1201
1769
|
// Normalize lastUpdated to Date (for cache safety)
|
|
1202
1770
|
const normalizedState = { ...state };
|
|
@@ -1212,16 +1780,87 @@ class AXPWorkflowManager {
|
|
|
1212
1780
|
return null;
|
|
1213
1781
|
}
|
|
1214
1782
|
}
|
|
1215
|
-
|
|
1216
|
-
|
|
1783
|
+
/**
|
|
1784
|
+
* Claim a pooled workflow task (assign current user on the bookmark without advancing the workflow).
|
|
1785
|
+
* Supported only when the injected workflow engine implements {@link AXPWorkflowEngine.claimTask}.
|
|
1786
|
+
*/
|
|
1787
|
+
async claimTask(instanceId, bookmarkId, stepId) {
|
|
1788
|
+
const claim = this.workflowEngine.claimTask?.bind(this.workflowEngine);
|
|
1789
|
+
if (!claim) {
|
|
1790
|
+
return {
|
|
1791
|
+
success: false,
|
|
1792
|
+
instanceId,
|
|
1793
|
+
error: 'Claim task is not supported by this workflow engine',
|
|
1794
|
+
};
|
|
1795
|
+
}
|
|
1796
|
+
try {
|
|
1797
|
+
const result = await claim({ instanceId, bookmarkId, stepId });
|
|
1798
|
+
return {
|
|
1799
|
+
success: result.success,
|
|
1800
|
+
instanceId,
|
|
1801
|
+
error: result.error,
|
|
1802
|
+
errorCode: result.errorCode,
|
|
1803
|
+
};
|
|
1804
|
+
}
|
|
1805
|
+
catch (error) {
|
|
1806
|
+
const { message, code } = getWorkflowEngineErrorInfo(error);
|
|
1807
|
+
return {
|
|
1808
|
+
success: false,
|
|
1809
|
+
instanceId,
|
|
1810
|
+
error: message,
|
|
1811
|
+
errorCode: code,
|
|
1812
|
+
};
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
/**
|
|
1816
|
+
* Reassign a human-task bookmark to the current user without advancing the workflow.
|
|
1817
|
+
* Supported only when the injected workflow engine implements {@link AXPWorkflowEngine.reassignTaskToSelf}.
|
|
1818
|
+
*/
|
|
1819
|
+
async reassignTaskToSelf(instanceId, bookmarkId, stepId) {
|
|
1820
|
+
const reassign = this.workflowEngine.reassignTaskToSelf?.bind(this.workflowEngine);
|
|
1821
|
+
if (!reassign) {
|
|
1822
|
+
return {
|
|
1823
|
+
success: false,
|
|
1824
|
+
instanceId,
|
|
1825
|
+
error: 'Reassign task is not supported by this workflow engine',
|
|
1826
|
+
};
|
|
1827
|
+
}
|
|
1828
|
+
try {
|
|
1829
|
+
const result = await reassign({ instanceId, bookmarkId, stepId });
|
|
1830
|
+
return {
|
|
1831
|
+
success: result.success,
|
|
1832
|
+
instanceId,
|
|
1833
|
+
error: result.error,
|
|
1834
|
+
errorCode: result.errorCode,
|
|
1835
|
+
};
|
|
1836
|
+
}
|
|
1837
|
+
catch (error) {
|
|
1838
|
+
const { message, code } = getWorkflowEngineErrorInfo(error);
|
|
1839
|
+
return {
|
|
1840
|
+
success: false,
|
|
1841
|
+
instanceId,
|
|
1842
|
+
error: message,
|
|
1843
|
+
errorCode: code,
|
|
1844
|
+
};
|
|
1845
|
+
}
|
|
1846
|
+
}
|
|
1847
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowManager, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1848
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowManager, providedIn: 'root' }); }
|
|
1217
1849
|
}
|
|
1218
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1850
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowManager, decorators: [{
|
|
1219
1851
|
type: Injectable,
|
|
1220
1852
|
args: [{
|
|
1221
|
-
providedIn: 'root'
|
|
1853
|
+
providedIn: 'root',
|
|
1222
1854
|
}]
|
|
1223
1855
|
}] });
|
|
1224
1856
|
|
|
1857
|
+
const AXP_WORKFLOW_PROVIDER = new InjectionToken('AXP_WORKFLOW_PROVIDER', {
|
|
1858
|
+
factory: () => [],
|
|
1859
|
+
});
|
|
1860
|
+
const AXP_WORKFLOW_CATEGORY_PROVIDER = new InjectionToken('AXP_WORKFLOW_CATEGORY_PROVIDER', {
|
|
1861
|
+
factory: () => [],
|
|
1862
|
+
});
|
|
1863
|
+
|
|
1225
1864
|
//#endregion
|
|
1226
1865
|
/**
|
|
1227
1866
|
* Local engine implementation that manages workflow progression and state.
|
|
@@ -1232,16 +1871,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
1232
1871
|
* - Maintains workflow state in memory
|
|
1233
1872
|
* - Does not require backend API calls
|
|
1234
1873
|
*
|
|
1235
|
-
* Execution of frontend tasks is handled by AXPWorkflowManager via
|
|
1874
|
+
* Execution of frontend tasks is handled by AXPWorkflowManager via ActivityExecutor.
|
|
1236
1875
|
* This engine only manages workflow progression and state storage.
|
|
1237
1876
|
*
|
|
1238
1877
|
* This is the DEFAULT engine provider. Applications can override it with
|
|
1239
1878
|
* an API-based engine implementation.
|
|
1240
1879
|
*/
|
|
1241
1880
|
class AXPWorkflowLocalEngine {
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
this.
|
|
1881
|
+
constructor() {
|
|
1882
|
+
//#region ---- Services & Dependencies ----
|
|
1883
|
+
this.activityDefinitionService = inject(AXPActivityDefinitionService);
|
|
1884
|
+
this.workflowProviders = inject(AXP_WORKFLOW_PROVIDER, { optional: true }) || [];
|
|
1885
|
+
this.multiLanguageResolver = inject(AXTranslationService);
|
|
1245
1886
|
//#endregion
|
|
1246
1887
|
//#region ---- Instance Storage ----
|
|
1247
1888
|
/**
|
|
@@ -1267,20 +1908,30 @@ class AXPWorkflowLocalEngine {
|
|
|
1267
1908
|
* Backend activities are skipped.
|
|
1268
1909
|
*/
|
|
1269
1910
|
async start(request) {
|
|
1911
|
+
console.log(`[WorkflowLocalEngine] 🚀 Starting workflow: ${request.workflowId}`, request);
|
|
1270
1912
|
// Generate instance ID
|
|
1271
1913
|
const instanceId = AXPDataGenerator.uuid();
|
|
1272
1914
|
const now = new Date();
|
|
1273
1915
|
// Load workflow definition
|
|
1916
|
+
console.log(`[WorkflowLocalEngine] 📥 Loading workflow definition: ${request.workflowId}`);
|
|
1274
1917
|
const definition = await this.getDefinition(request.workflowId);
|
|
1275
1918
|
if (!definition) {
|
|
1919
|
+
console.error(`[WorkflowLocalEngine] ❌ Workflow definition not found: ${request.workflowId}`);
|
|
1276
1920
|
throw new Error(`Workflow definition not found: ${request.workflowId}`);
|
|
1277
1921
|
}
|
|
1922
|
+
console.log(`[WorkflowLocalEngine] ✅ Definition loaded:`, {
|
|
1923
|
+
name: definition.name,
|
|
1924
|
+
activitiesCount: definition.graph?.activities?.length || 0,
|
|
1925
|
+
connectionsCount: definition.graph?.connections?.length || 0,
|
|
1926
|
+
});
|
|
1278
1927
|
// Initialize workflow state
|
|
1279
1928
|
const state = {
|
|
1280
1929
|
instanceId,
|
|
1281
1930
|
workflowId: request.workflowId,
|
|
1282
1931
|
status: 'running',
|
|
1283
1932
|
variables: {},
|
|
1933
|
+
activityOutputs: {},
|
|
1934
|
+
lastActivityOutput: undefined,
|
|
1284
1935
|
input: request.input || {},
|
|
1285
1936
|
output: undefined,
|
|
1286
1937
|
lastUpdated: now,
|
|
@@ -1297,13 +1948,22 @@ class AXPWorkflowLocalEngine {
|
|
|
1297
1948
|
// Store instance
|
|
1298
1949
|
this.instances.set(instanceId, localState);
|
|
1299
1950
|
// Execute workflow steps
|
|
1951
|
+
console.log(`[WorkflowLocalEngine] ⚙️ Executing workflow steps...`);
|
|
1300
1952
|
const pendingTask = await this.executeWorkflowSteps(localState);
|
|
1301
1953
|
// Update state
|
|
1302
1954
|
localState.state.lastUpdated = new Date();
|
|
1955
|
+
console.log(`[WorkflowLocalEngine] ✅ Workflow started:`, {
|
|
1956
|
+
instanceId,
|
|
1957
|
+
status: localState.state.status,
|
|
1958
|
+
hasPendingTask: !!pendingTask,
|
|
1959
|
+
pendingTaskType: pendingTask?.activityType,
|
|
1960
|
+
});
|
|
1303
1961
|
return {
|
|
1304
1962
|
instanceId,
|
|
1305
1963
|
state: localState.state,
|
|
1306
1964
|
pendingTask: pendingTask || null,
|
|
1965
|
+
activityOutputs: localState.state.activityOutputs,
|
|
1966
|
+
lastActivityOutput: localState.state.lastActivityOutput,
|
|
1307
1967
|
};
|
|
1308
1968
|
}
|
|
1309
1969
|
/**
|
|
@@ -1324,11 +1984,18 @@ class AXPWorkflowLocalEngine {
|
|
|
1324
1984
|
throw new Error(`Workflow instance not found: ${request.instanceId}`);
|
|
1325
1985
|
}
|
|
1326
1986
|
// Store activity result (from external execution)
|
|
1987
|
+
const outcome = request.outcome ?? 'Done';
|
|
1327
1988
|
localState.activityResults.set(request.stepId, {
|
|
1328
1989
|
output: request.userInput || {},
|
|
1329
|
-
outcome
|
|
1990
|
+
outcome,
|
|
1330
1991
|
});
|
|
1331
1992
|
localState.completedActivities.add(request.stepId);
|
|
1993
|
+
// Store activity output for expression evaluation
|
|
1994
|
+
localState.state.activityOutputs = {
|
|
1995
|
+
...(localState.state.activityOutputs || {}),
|
|
1996
|
+
[request.stepId]: request.userInput || {},
|
|
1997
|
+
};
|
|
1998
|
+
localState.state.lastActivityOutput = request.userInput || {};
|
|
1332
1999
|
// Merge output/userInput into state variables
|
|
1333
2000
|
if (request.userInput) {
|
|
1334
2001
|
localState.state.variables = {
|
|
@@ -1336,6 +2003,11 @@ class AXPWorkflowLocalEngine {
|
|
|
1336
2003
|
...(request.userInput || {}),
|
|
1337
2004
|
};
|
|
1338
2005
|
}
|
|
2006
|
+
localState.state.variables = {
|
|
2007
|
+
...localState.state.variables,
|
|
2008
|
+
[`${request.stepId}_outcome`]: outcome,
|
|
2009
|
+
[`${request.stepId}_activityOutput`]: request.userInput || {},
|
|
2010
|
+
};
|
|
1339
2011
|
// Mark activity as completed and continue progression
|
|
1340
2012
|
// Continue progressing workflow steps (skipping backend activities)
|
|
1341
2013
|
const nextTask = await this.executeWorkflowSteps(localState);
|
|
@@ -1348,7 +2020,7 @@ class AXPWorkflowLocalEngine {
|
|
|
1348
2020
|
}
|
|
1349
2021
|
return {
|
|
1350
2022
|
output: request.userInput || {},
|
|
1351
|
-
outcomes: { [
|
|
2023
|
+
outcomes: { [outcome]: true },
|
|
1352
2024
|
state: localState.state,
|
|
1353
2025
|
nextTask: nextTask || null,
|
|
1354
2026
|
};
|
|
@@ -1371,15 +2043,26 @@ class AXPWorkflowLocalEngine {
|
|
|
1371
2043
|
//#endregion
|
|
1372
2044
|
//#region ---- Private Methods ----
|
|
1373
2045
|
/**
|
|
1374
|
-
* Get workflow definition from available
|
|
2046
|
+
* Get workflow definition from available providers.
|
|
1375
2047
|
*/
|
|
1376
2048
|
async getDefinition(workflowId) {
|
|
1377
|
-
// Try all
|
|
1378
|
-
const
|
|
1379
|
-
for (const
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
2049
|
+
// Try all providers in order
|
|
2050
|
+
const resolvedProviders = await Promise.allSettled(this.workflowProviders);
|
|
2051
|
+
for (const p of resolvedProviders) {
|
|
2052
|
+
if (p.status === 'fulfilled' && p.value) {
|
|
2053
|
+
const provider = p.value;
|
|
2054
|
+
// Check if provider has getByName method
|
|
2055
|
+
if (typeof provider.getByName === 'function') {
|
|
2056
|
+
try {
|
|
2057
|
+
const definition = await provider.getByName(workflowId);
|
|
2058
|
+
if (definition) {
|
|
2059
|
+
return definition;
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
catch {
|
|
2063
|
+
// Continue on error - try other providers
|
|
2064
|
+
}
|
|
2065
|
+
}
|
|
1383
2066
|
}
|
|
1384
2067
|
}
|
|
1385
2068
|
return null;
|
|
@@ -1398,13 +2081,13 @@ class AXPWorkflowLocalEngine {
|
|
|
1398
2081
|
const connections = graph.connections || [];
|
|
1399
2082
|
// Build activity map
|
|
1400
2083
|
const activityMap = new Map();
|
|
1401
|
-
activities.forEach(activity => {
|
|
2084
|
+
activities.forEach((activity) => {
|
|
1402
2085
|
activityMap.set(activity.id, activity);
|
|
1403
2086
|
});
|
|
1404
2087
|
// Build connection graph
|
|
1405
2088
|
const outgoingConnections = new Map();
|
|
1406
2089
|
const incomingConnections = new Map();
|
|
1407
|
-
connections.forEach(conn => {
|
|
2090
|
+
connections.forEach((conn) => {
|
|
1408
2091
|
const sourceId = conn.source.activtyName;
|
|
1409
2092
|
const targetId = conn.target.activtyName;
|
|
1410
2093
|
if (!outgoingConnections.has(sourceId)) {
|
|
@@ -1450,8 +2133,18 @@ class AXPWorkflowLocalEngine {
|
|
|
1450
2133
|
currentActivityId = nextId ?? undefined;
|
|
1451
2134
|
continue;
|
|
1452
2135
|
}
|
|
1453
|
-
//
|
|
1454
|
-
|
|
2136
|
+
// Get activity definition to retrieve executionMode and title
|
|
2137
|
+
console.log(`[WorkflowLocalEngine] 🔍 Getting activity definition for: ${activity.name}`);
|
|
2138
|
+
const activityDefinition = await this.activityDefinitionService.getActivityByName(activity.name);
|
|
2139
|
+
console.log(`[WorkflowLocalEngine] 📋 Activity definition:`, {
|
|
2140
|
+
name: activityDefinition?.name,
|
|
2141
|
+
type: activityDefinition?.type,
|
|
2142
|
+
executionMode: activityDefinition?.executionMode,
|
|
2143
|
+
title: activityDefinition?.title,
|
|
2144
|
+
found: !!activityDefinition,
|
|
2145
|
+
});
|
|
2146
|
+
const executionMode = activityDefinition?.executionMode || 'frontend';
|
|
2147
|
+
const activityTitle = this.multiLanguageResolver.resolve(activityDefinition?.title) || activityDefinition?.name;
|
|
1455
2148
|
// Handle backend activities: skip
|
|
1456
2149
|
if (executionMode === 'backend') {
|
|
1457
2150
|
console.log(`[WorkflowLocalEngine] ⏭️ Skipping backend activity: ${activity.name} (${activity.id})`);
|
|
@@ -1468,14 +2161,14 @@ class AXPWorkflowLocalEngine {
|
|
|
1468
2161
|
// Handle frontend/both activities: return as pendingTask (do NOT execute)
|
|
1469
2162
|
if (executionMode === 'frontend' || executionMode === 'both') {
|
|
1470
2163
|
// Create task for external execution
|
|
2164
|
+
// Note: Expression evaluation will be done by ActivityExecutor
|
|
1471
2165
|
const task = {
|
|
1472
2166
|
taskToken: AXPDataGenerator.uuid(),
|
|
1473
2167
|
activityId: activity.id,
|
|
1474
2168
|
activityType: activity.name,
|
|
1475
|
-
activityName:
|
|
2169
|
+
activityName: activityTitle || undefined,
|
|
1476
2170
|
executionMode: executionMode,
|
|
1477
|
-
input: activity.inputs || {},
|
|
1478
|
-
config: activity.customProperties || {},
|
|
2171
|
+
input: activity.inputs || {}, // Pass raw inputs - executor will evaluate
|
|
1479
2172
|
};
|
|
1480
2173
|
// Store task token for secure resume
|
|
1481
2174
|
this.taskTokens.set(task.taskToken, {
|
|
@@ -1524,27 +2217,54 @@ class AXPWorkflowLocalEngine {
|
|
|
1524
2217
|
}
|
|
1525
2218
|
return null;
|
|
1526
2219
|
}
|
|
1527
|
-
|
|
1528
|
-
|
|
2220
|
+
async frontActivtyComplete(request) {
|
|
2221
|
+
const localState = this.instances.get(request.instanceId);
|
|
2222
|
+
if (!localState) {
|
|
2223
|
+
throw new Error(`Workflow instance not found: ${request.instanceId}`);
|
|
2224
|
+
}
|
|
2225
|
+
// Store activity result
|
|
2226
|
+
const outcome = request.outcome ?? 'Done';
|
|
2227
|
+
localState.activityResults.set(request.activityNode, {
|
|
2228
|
+
output: request.output || {},
|
|
2229
|
+
outcome,
|
|
2230
|
+
});
|
|
2231
|
+
localState.completedActivities.add(request.activityNode);
|
|
2232
|
+
// Store outputs for expression evaluation
|
|
2233
|
+
localState.state.activityOutputs = {
|
|
2234
|
+
...(localState.state.activityOutputs || {}),
|
|
2235
|
+
[request.activityNode]: request.output || {},
|
|
2236
|
+
};
|
|
2237
|
+
localState.state.lastActivityOutput = request.output || {};
|
|
2238
|
+
// Merge output into workflow variables
|
|
2239
|
+
localState.state.variables = {
|
|
2240
|
+
...localState.state.variables,
|
|
2241
|
+
...(request.output || {}),
|
|
2242
|
+
};
|
|
2243
|
+
// Continue workflow progression
|
|
2244
|
+
const nextTask = await this.executeWorkflowSteps(localState);
|
|
2245
|
+
// Update state timestamp
|
|
2246
|
+
localState.state.lastUpdated = new Date();
|
|
2247
|
+
// Determine final status
|
|
2248
|
+
if (!nextTask && localState.state.status === 'running') {
|
|
2249
|
+
localState.state.status = 'completed';
|
|
2250
|
+
localState.state.output = localState.state.variables;
|
|
2251
|
+
}
|
|
2252
|
+
return {
|
|
2253
|
+
output: request.output || {},
|
|
2254
|
+
outcomes: { [outcome]: true },
|
|
2255
|
+
nextTask: nextTask || null,
|
|
2256
|
+
state: localState.state,
|
|
2257
|
+
};
|
|
2258
|
+
}
|
|
2259
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowLocalEngine, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2260
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowLocalEngine }); }
|
|
1529
2261
|
}
|
|
1530
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2262
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowLocalEngine, decorators: [{
|
|
1531
2263
|
type: Injectable
|
|
1532
|
-
}]
|
|
1533
|
-
type: Optional
|
|
1534
|
-
}, {
|
|
1535
|
-
type: Inject,
|
|
1536
|
-
args: [AXP_WORKFLOW_DEFINITION_LOADER]
|
|
1537
|
-
}] }] });
|
|
2264
|
+
}] });
|
|
1538
2265
|
|
|
1539
2266
|
// Workflow Runtime Services
|
|
1540
2267
|
|
|
1541
|
-
const AXP_WORKFLOW_PROVIDER = new InjectionToken('AXP_WORKFLOW_PROVIDER', {
|
|
1542
|
-
factory: () => [],
|
|
1543
|
-
});
|
|
1544
|
-
const AXP_WORKFLOW_CATEGORY_PROVIDER = new InjectionToken('AXP_WORKFLOW_CATEGORY_PROVIDER', {
|
|
1545
|
-
factory: () => [],
|
|
1546
|
-
});
|
|
1547
|
-
|
|
1548
2268
|
//#region ---- Imports ----
|
|
1549
2269
|
//#endregion
|
|
1550
2270
|
/**
|
|
@@ -1665,7 +2385,7 @@ class AXPWorkflowDefinitionService {
|
|
|
1665
2385
|
* - Returns cached result on subsequent calls
|
|
1666
2386
|
*
|
|
1667
2387
|
* @param categoryId - Category ID to get workflow definitions from
|
|
1668
|
-
* @returns Array of workflow
|
|
2388
|
+
* @returns Array of workflow definitions
|
|
1669
2389
|
*/
|
|
1670
2390
|
async getWorkflowsByCategoryId(categoryId) {
|
|
1671
2391
|
// ✅ Fast path: Return cached result
|
|
@@ -1690,12 +2410,12 @@ class AXPWorkflowDefinitionService {
|
|
|
1690
2410
|
return requestPromise;
|
|
1691
2411
|
}
|
|
1692
2412
|
/**
|
|
1693
|
-
* Get single workflow definition
|
|
2413
|
+
* Get single workflow definition by name with O(1) lookup
|
|
1694
2414
|
*
|
|
1695
2415
|
* Optimization: Uses Map for instant retrieval
|
|
1696
2416
|
*
|
|
1697
2417
|
* @param name - Workflow name (unique identifier)
|
|
1698
|
-
* @returns Workflow definition
|
|
2418
|
+
* @returns Workflow definition or undefined if not found
|
|
1699
2419
|
*/
|
|
1700
2420
|
async getWorkflowByName(name) {
|
|
1701
2421
|
// ✅ Fast path: O(1) lookup in cache
|
|
@@ -1724,13 +2444,18 @@ class AXPWorkflowDefinitionService {
|
|
|
1724
2444
|
}
|
|
1725
2445
|
}
|
|
1726
2446
|
// ✅ Try loading the workflow definition to find its category
|
|
2447
|
+
// Note: AXPWorkflowDefinition doesn't have category field
|
|
2448
|
+
// Category is managed separately through category providers
|
|
2449
|
+
// This method searches through cached categories
|
|
1727
2450
|
const definition = await this.getWorkflowByName(workflowName);
|
|
1728
|
-
if (definition
|
|
1729
|
-
//
|
|
2451
|
+
if (definition) {
|
|
2452
|
+
// Search through all categories to find which one contains this workflow
|
|
1730
2453
|
const categories = await this.getCategories();
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
2454
|
+
for (const category of categories) {
|
|
2455
|
+
const workflows = await this.getWorkflowsByCategoryId(category.id);
|
|
2456
|
+
if (workflows.some(w => w.name === workflowName)) {
|
|
2457
|
+
return category.id;
|
|
2458
|
+
}
|
|
1734
2459
|
}
|
|
1735
2460
|
}
|
|
1736
2461
|
return undefined;
|
|
@@ -1856,12 +2581,12 @@ class AXPWorkflowDefinitionService {
|
|
|
1856
2581
|
const resolvedProviders = await Promise.allSettled(this.workflowProviders);
|
|
1857
2582
|
// Try providers first
|
|
1858
2583
|
for (const p of resolvedProviders) {
|
|
1859
|
-
if (p.status === 'fulfilled' && p.value && typeof p.value.
|
|
2584
|
+
if (p.status === 'fulfilled' && p.value && typeof p.value.getByName === 'function') {
|
|
1860
2585
|
try {
|
|
1861
|
-
const
|
|
1862
|
-
if (
|
|
1863
|
-
this.workflowsByName.set(name,
|
|
1864
|
-
return
|
|
2586
|
+
const definition = await p.value.getByName(name);
|
|
2587
|
+
if (definition) {
|
|
2588
|
+
this.workflowsByName.set(name, definition);
|
|
2589
|
+
return definition;
|
|
1865
2590
|
}
|
|
1866
2591
|
}
|
|
1867
2592
|
catch {
|
|
@@ -1955,18 +2680,16 @@ class AXPWorkflowDefinitionService {
|
|
|
1955
2680
|
this.pendingWorkflowsRequests.clear();
|
|
1956
2681
|
this.pendingWorkflowRequests.clear();
|
|
1957
2682
|
}
|
|
1958
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1959
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
2683
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowDefinitionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2684
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowDefinitionService, providedIn: 'root' }); }
|
|
1960
2685
|
}
|
|
1961
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2686
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowDefinitionService, decorators: [{
|
|
1962
2687
|
type: Injectable,
|
|
1963
2688
|
args: [{
|
|
1964
2689
|
providedIn: 'root',
|
|
1965
2690
|
}]
|
|
1966
2691
|
}] });
|
|
1967
2692
|
|
|
1968
|
-
// Workflow Definition Types (Storage/Database)
|
|
1969
|
-
|
|
1970
2693
|
class AXPWorkflowModule {
|
|
1971
2694
|
static forRoot(config) {
|
|
1972
2695
|
return {
|
|
@@ -2050,9 +2773,9 @@ class AXPWorkflowModule {
|
|
|
2050
2773
|
f();
|
|
2051
2774
|
});
|
|
2052
2775
|
}
|
|
2053
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2054
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "
|
|
2055
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "
|
|
2776
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowModule, deps: [{ token: 'AXPWorkflowModuleFactory', optional: true }], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
2777
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowModule }); }
|
|
2778
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowModule, providers: [
|
|
2056
2779
|
AXPWorkflowLocalEngine,
|
|
2057
2780
|
{
|
|
2058
2781
|
provide: AXP_WORKFLOW_ENGINE,
|
|
@@ -2061,7 +2784,7 @@ class AXPWorkflowModule {
|
|
|
2061
2784
|
AXPWorkflowManager,
|
|
2062
2785
|
] }); }
|
|
2063
2786
|
}
|
|
2064
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2787
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowModule, decorators: [{
|
|
2065
2788
|
type: NgModule,
|
|
2066
2789
|
args: [{
|
|
2067
2790
|
imports: [],
|
|
@@ -2087,5 +2810,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
2087
2810
|
* Generated bundle index. Do not edit.
|
|
2088
2811
|
*/
|
|
2089
2812
|
|
|
2090
|
-
export { AXPActivityDefinitionService, AXPWorkflowAction, AXPWorkflowContext, AXPWorkflowDefinitionService, AXPWorkflowError, AXPWorkflowEventService, AXPWorkflowFunction, AXPWorkflowLocalEngine, AXPWorkflowManager, AXPWorkflowModule, AXPWorkflowRegistryService, AXPWorkflowService, AXP_ACTIVITY_CATEGORY_PROVIDER, AXP_ACTIVITY_PROVIDER, AXP_WORKFLOW_CATEGORY_PROVIDER,
|
|
2813
|
+
export { AXPActivityDefinitionService, AXPWorkflowAction, AXPWorkflowContext, AXPWorkflowDefinitionService, AXPWorkflowEngineError, AXPWorkflowError, AXPWorkflowEventService, AXPWorkflowFunction, AXPWorkflowLocalEngine, AXPWorkflowManager, AXPWorkflowModule, AXPWorkflowRegistryService, AXPWorkflowService, AXP_ACTIVITY_CATEGORY_PROVIDER, AXP_ACTIVITY_PROVIDER, AXP_WORKFLOW_CATEGORY_PROVIDER, AXP_WORKFLOW_CONTINUATION_HOOK, AXP_WORKFLOW_ENGINE, AXP_WORKFLOW_ERROR_CODES, AXP_WORKFLOW_PROVIDER, AXP_WORKFLOW_SUPPRESS_CONTINUATION_INPUT_KEY, AXP_WORKFLOW_TASK_BOARD_ACTIVITY_TYPES, ActivityExecutor, WorkflowExpressionScopeService, axpIsWorkflowInlineFrontendTask, axpIsWorkflowInteractiveFrontendTask, axpIsWorkflowTaskBoardActivityType, axpResolveWorkflowContinuationBeforeInteractive, axpShouldOfferBeforeInteractiveFlow, axpShouldOfferWorkflowContinuationAfterStep, axpShouldSkipBeforeInteractiveFromMetadata, createWorkFlowEvent, getWorkflowEngineErrorCode, getWorkflowEngineErrorInfo, isWorkflowContinuationSuppressed, ofType };
|
|
2091
2814
|
//# sourceMappingURL=acorex-platform-workflow.mjs.map
|