@acorex/connectivity 20.6.0-next.1 → 20.6.0-next.3

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.
@@ -11,12 +11,13 @@ import { RootConfig, AXMUsersEntityService, AXMPolicyService } from '@acorex/mod
11
11
  import { Router } from '@angular/router';
12
12
  import { of, delay, filter, take, map, throttleTime } from 'rxjs';
13
13
  import { AXMPermissionsKeys, RootConfig as RootConfig$8, AXMFormTemplateTypes } from '@acorex/modules/form-template-management';
14
- import { AXMPermissionsKeys as AXMPermissionsKeys$1, RootConfig as RootConfig$p } from '@acorex/modules/help-desk';
14
+ import { AXMPermissionsKeys as AXMPermissionsKeys$1, RootConfig as RootConfig$q } from '@acorex/modules/help-desk';
15
15
  import { RootConfig as RootConfig$1 } from '@acorex/modules/calendar-management';
16
16
  import { AXPFileStorageStatus, AXPFileStorageService, AXVChangeType as AXVChangeType$1, AXP_SEARCH_PROVIDER, AXPLockService, AXPVersioningService, AXPAppVersionService } from '@acorex/platform/common';
17
17
  import Dexie from 'dexie';
18
18
  import { AXFileService } from '@acorex/core/file';
19
19
  import { AXPActivityProviderService, AXP_ACTIVITY_CATEGORY_PROVIDER, AXP_ACTIVITY_PROVIDER, AXPWorkflowExecutionService } from '@acorex/platform/workflow';
20
+ import { AXPCommandService, provideCommandSetups, provideQuerySetups, AXPQueryService, AXPRuntimeModule } from '@acorex/platform/runtime';
20
21
  import { RootConfig as RootConfig$2 } from '@acorex/modules/contact-management';
21
22
  import { RootConfig as RootConfig$3 } from '@acorex/modules/content-management';
22
23
  import { AXMChatManagementService, AXMChatRealtimeService, AXMCommentManagementService, AXMCommentRealtimeService, RootConfig as RootConfig$4 } from '@acorex/modules/conversation';
@@ -25,7 +26,6 @@ import { AXPTaskBoardShortcut, AXPTaskBoardWidget, RootConfig as RootConfig$k, A
25
26
  import { AXPMyNotificationDashboardWidget, RootConfig as RootConfig$e, AXMNotificationEntityServiceImpl, AXMNotificationEntityService } from '@acorex/modules/notification-management';
26
27
  import { RootConfig as RootConfig$6, AXMMetaDataDefinitionService } from '@acorex/modules/data-management';
27
28
  import { get, upperFirst, set } from 'lodash-es';
28
- import { provideQuerySetups, AXPCommandService, provideCommandSetups, AXPQueryService, AXPRuntimeModule } from '@acorex/platform/runtime';
29
29
  import { AXMDistributionServiceImpl, AXMDocumentService, AXMDistributionInteractionService, RootConfig as RootConfig$7, AXMFolderServiceImpl, AXMDocumentServiceImpl, AXMReviewService, AXMReviewServiceImpl, AXMDistributionInteractionServiceImpl, AXMFolderService, AXMDistributionService } from '@acorex/modules/document-management';
30
30
  import { AXDataSource } from '@acorex/cdk/common';
31
31
  import { AXPWidgetsCatalog } from '@acorex/platform/layout/widget-core';
@@ -44,10 +44,11 @@ import { RootConfig as RootConfig$i } from '@acorex/modules/project-management';
44
44
  import * as i1 from '@acorex/components/dialog';
45
45
  import * as i2 from '@acorex/core/translation';
46
46
  import { RootConfig as RootConfig$l } from '@acorex/modules/training-management';
47
+ import { RootConfig as RootConfig$m } from '@acorex/modules/workflow-management';
47
48
  import { AXCalendarService } from '@acorex/core/date-time';
48
- import { RootConfig as RootConfig$m } from '@acorex/modules/application-management';
49
- import { RootConfig as RootConfig$n } from '@acorex/modules/assessment-management';
50
- import { RootConfig as RootConfig$o } from '@acorex/modules/customer-management';
49
+ import { RootConfig as RootConfig$n } from '@acorex/modules/application-management';
50
+ import { RootConfig as RootConfig$o } from '@acorex/modules/assessment-management';
51
+ import { RootConfig as RootConfig$p } from '@acorex/modules/customer-management';
51
52
  import { AXCExternalAuthorizationService } from '@acorex/connectivity/utils';
52
53
 
53
54
  class AXCUserPassStrategyMock extends AXPAuthStrategy {
@@ -1516,7 +1517,7 @@ function computeFileDiff(prev, next, basePath, push) {
1516
1517
  }
1517
1518
  //#endregion
1518
1519
  //#region ---- Service ----
1519
- class VersioningService {
1520
+ class AXCVersioningService {
1520
1521
  constructor() {
1521
1522
  this.db = axVersionDB;
1522
1523
  this.fileStorage = inject(AXPFileStorageService);
@@ -1613,10 +1614,10 @@ class VersioningService {
1613
1614
  newValue: d.newValue,
1614
1615
  }));
1615
1616
  }
1616
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: VersioningService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1617
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: VersioningService, providedIn: 'root' }); }
1617
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCVersioningService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1618
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCVersioningService, providedIn: 'root' }); }
1618
1619
  }
1619
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: VersioningService, decorators: [{
1620
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCVersioningService, decorators: [{
1620
1621
  type: Injectable,
1621
1622
  args: [{ providedIn: 'root' }]
1622
1623
  }] });
@@ -2665,8 +2666,120 @@ class AXCActivityProvider {
2665
2666
  },
2666
2667
  });
2667
2668
  // ============================================
2669
+ // SECURITY ACTIVITIES
2670
+ // ============================================
2671
+ context.registerActivity({
2672
+ key: 'workflow-activity:check-permission',
2673
+ descriptor: {
2674
+ type: 'workflow-activity:check-permission',
2675
+ displayName: 'Check Permission',
2676
+ description: 'Checks if current user has specific permission',
2677
+ category: 'Security',
2678
+ icon: 'fa-light fa-shield-check',
2679
+ executionMode: 'backend', // Backend activity - permission check on server
2680
+ inputs: [
2681
+ {
2682
+ name: 'permission',
2683
+ title: 'Permission',
2684
+ description: 'Permission key to check (e.g., "Users.Create")',
2685
+ schema: {
2686
+ dataType: 'string',
2687
+ },
2688
+ validations: [{ rule: 'required' }],
2689
+ },
2690
+ {
2691
+ name: 'userId',
2692
+ title: 'User ID',
2693
+ description: 'User ID to check (optional, defaults to current user)',
2694
+ schema: {
2695
+ dataType: 'string',
2696
+ },
2697
+ },
2698
+ ],
2699
+ outputs: [
2700
+ {
2701
+ name: 'hasPermission',
2702
+ title: 'Has Permission',
2703
+ description: 'Whether user has the permission',
2704
+ schema: {
2705
+ dataType: 'boolean',
2706
+ },
2707
+ },
2708
+ ],
2709
+ outcomes: ['HasPermission', 'NoPermission'],
2710
+ isBrowsable: true,
2711
+ isContainer: false,
2712
+ },
2713
+ });
2714
+ // ============================================
2668
2715
  // FORM ACTIVITIES
2669
2716
  // ============================================
2717
+ context.registerActivity({
2718
+ key: 'workflow-activity:show-dialog',
2719
+ descriptor: {
2720
+ type: 'workflow-activity:show-dialog',
2721
+ displayName: 'Show Dialog',
2722
+ description: 'Shows a dialog with form or custom content',
2723
+ category: 'Dialog',
2724
+ icon: 'fa-light fa-window',
2725
+ executionMode: 'frontend', // Frontend activity - shows UI dialog
2726
+ inputs: [
2727
+ {
2728
+ name: 'title',
2729
+ title: 'Title',
2730
+ description: 'Dialog title',
2731
+ schema: {
2732
+ dataType: 'string',
2733
+ },
2734
+ },
2735
+ {
2736
+ name: 'formDefinition',
2737
+ title: 'Form Definition',
2738
+ description: 'Form definition key or inline definition',
2739
+ schema: {
2740
+ dataType: 'string',
2741
+ },
2742
+ },
2743
+ {
2744
+ name: 'size',
2745
+ title: 'Size',
2746
+ description: 'Dialog size (sm, md, lg, xl)',
2747
+ schema: {
2748
+ dataType: 'string',
2749
+ },
2750
+ },
2751
+ {
2752
+ name: 'closeButton',
2753
+ title: 'Close Button',
2754
+ description: 'Show close button',
2755
+ schema: {
2756
+ dataType: 'boolean',
2757
+ },
2758
+ },
2759
+ ],
2760
+ outputs: [
2761
+ {
2762
+ name: 'formData',
2763
+ title: 'Form Data',
2764
+ description: 'Form data submitted by user',
2765
+ schema: {
2766
+ dataType: 'object',
2767
+ },
2768
+ },
2769
+ {
2770
+ name: 'action',
2771
+ title: 'Action',
2772
+ description: 'Action taken by user',
2773
+ schema: {
2774
+ dataType: 'string',
2775
+ },
2776
+ },
2777
+ ],
2778
+ outcomes: ['Submitted', 'Cancelled'],
2779
+ isBrowsable: true,
2780
+ isContainer: false,
2781
+ },
2782
+ });
2670
2783
  context.registerActivity({
2671
2784
  key: 'workflow-activity:show-form',
2672
2785
  descriptor: {
@@ -2853,7 +2966,7 @@ class AXCActivityProvider {
2853
2966
  isContainer: false,
2854
2967
  },
2855
2968
  });
2856
- console.log('[AXPBuiltinActivityProvider] Registered 17 built-in activities');
2969
+ console.log('[AXPBuiltinActivityProvider] Registered 19 built-in activities');
2857
2970
  }
2858
2971
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCActivityProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2859
2972
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCActivityProvider }); }
@@ -2862,14 +2975,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
2862
2975
  type: Injectable
2863
2976
  }] });
2864
2977
 
2865
- //#endregion
2866
2978
  //#region ---- Dexie DB ----
2867
2979
  /**
2868
- * Dexie database for workflow execution states.
2980
+ * Dexie database for workflow instances.
2869
2981
  */
2870
2982
  class AXCWorkflowExecutionDB extends Dexie {
2871
2983
  constructor() {
2872
2984
  super('ACoreXWorkflowExecutions');
2985
+ this.version(2).stores({
2986
+ instances: 'id, definitionId, status, subStatus, createdAt, updatedAt',
2987
+ });
2988
+ // Migration from v1 to v2: clear old executions table
2873
2989
  this.version(1).stores({
2874
2990
  executions: 'executionId, workflowId, status, currentStepId, lastUpdated',
2875
2991
  });
@@ -2899,13 +3015,15 @@ class AXCWorkflowExecutionService {
2899
3015
  constructor() {
2900
3016
  this.db = axWorkflowExecutionDB;
2901
3017
  this.activityProviderService = inject(AXPActivityProviderService);
3018
+ this.commandService = inject(AXPCommandService);
2902
3019
  }
2903
3020
  /**
2904
3021
  * Start a new workflow execution.
3022
+ * Creates a workflow instance and stores it in IndexedDB.
2905
3023
  */
2906
3024
  async startExecution(request) {
2907
- const executionId = AXPDataGenerator.uuid();
2908
- const now = new Date();
3025
+ const instanceId = AXPDataGenerator.uuid();
3026
+ const now = new Date().toISOString();
2909
3027
  // Get workflow definition to find first step
2910
3028
  const workflowResponse = await this.getWorkflowDefinition({
2911
3029
  workflowId: request.workflowId
@@ -2913,129 +3031,188 @@ class AXCWorkflowExecutionService {
2913
3031
  if (!workflowResponse.workflow) {
2914
3032
  throw new Error(`Workflow definition not found: ${request.workflowId}`);
2915
3033
  }
2916
- // Find first step (root activity)
2917
- const rootActivity = workflowResponse.workflow.root;
2918
- const firstStepId = rootActivity.id || 'root';
2919
- const state = {
2920
- executionId,
2921
- workflowId: request.workflowId,
2922
- status: 'running',
2923
- currentStepId: firstStepId, // Set first step as current
2924
- variables: {},
2925
- input: request.input || {},
2926
- lastUpdated: now,
2927
- };
2928
- // Store in IndexedDB (executionId is primary key)
2929
- // Convert Date to ISO string for IndexedDB storage
2930
- const stateToStore = {
2931
- ...state,
2932
- lastUpdated: state.lastUpdated.toISOString(),
2933
- };
2934
- await this.db.executions.add(stateToStore, state.executionId);
2935
- // Return first task metadata (without full workflow definition)
2936
- const pendingTask = rootActivity ? this.createTaskFromStep(rootActivity, state) : null;
2937
- return {
2938
- executionId,
2939
- state,
2940
- pendingTask
2941
- };
2942
- }
2943
- /**
2944
- * Execute a backend activity.
2945
- *
2946
- * In mock implementation, this simulates backend activity execution.
2947
- * For real backend activities (execute-command, execute-query, set-variable),
2948
- * you would typically make an HTTP call. In mock, we just update state.
2949
- */
2950
- async executeBackendActivity(request) {
2951
- // Get current state
2952
- const state = await this.getExecutionState({
2953
- executionId: request.executionId,
3034
+ const workflow = workflowResponse.workflow;
3035
+ // Find first step from Flowchart (activity with no incoming connections)
3036
+ const flowchart = workflow.root;
3037
+ const activities = flowchart.activities || [];
3038
+ const connections = flowchart.connections || [];
3039
+ // Build connection map: target -> source[]
3040
+ const incomingConnections = new Map();
3041
+ connections.forEach((conn) => {
3042
+ const targetId = conn.target.activity;
3043
+ if (!incomingConnections.has(targetId)) {
3044
+ incomingConnections.set(targetId, []);
3045
+ }
3046
+ incomingConnections.get(targetId).push(conn.source.activity);
2954
3047
  });
2955
- if (!state) {
2956
- throw new Error(`Workflow execution not found: ${request.executionId}`);
3048
+ // Find root activity (activity with no incoming connections, or first activity)
3049
+ let firstActivity = null;
3050
+ for (const activity of activities) {
3051
+ if (!incomingConnections.has(activity.id)) {
3052
+ firstActivity = activity;
3053
+ break;
3054
+ }
2957
3055
  }
2958
- // Get workflow definition to find activity details
2959
- const workflowResponse = await this.getWorkflowDefinition({
2960
- workflowId: request.workflowId
2961
- });
2962
- const workflow = workflowResponse.workflow;
2963
- // Find current activity in workflow
2964
- const currentActivity = this.findActivityInWorkflow(workflow.root, request.activityId);
2965
- if (!currentActivity) {
2966
- throw new Error(`Activity '${request.activityId}' not found in workflow '${request.workflowId}'`);
2967
- }
2968
- // Execute backend activity using the new backend activity executor
2969
- const executionResult = await this.executeBackendActivityLocally(currentActivity, { ...state.variables, ...state.input }, state);
2970
- // Update state variables with activity output
2971
- const updatedVariables = {
2972
- ...state.variables,
2973
- ...executionResult.output
3056
+ // If no root found, use first activity
3057
+ if (!firstActivity && activities.length > 0) {
3058
+ firstActivity = activities[0];
3059
+ }
3060
+ const firstStepId = firstActivity?.id || 'root';
3061
+ // Create workflow state
3062
+ const workflowState = {
3063
+ id: `state-${instanceId}`,
3064
+ definitionId: workflow.definitionId,
3065
+ definitionVersion: workflow.version,
3066
+ correlationId: null,
3067
+ status: 'Running',
3068
+ subStatus: 'Executing',
3069
+ bookmarks: [],
3070
+ incidents: [],
3071
+ fault: null,
3072
+ completionCallbacks: [],
3073
+ activityExecutionContexts: firstActivity ? [{
3074
+ id: `ctx-${firstStepId}`,
3075
+ parentContextId: null,
3076
+ scheduledActivityNodeId: firstStepId,
3077
+ ownerActivityNodeId: null,
3078
+ properties: {},
3079
+ activityState: null,
3080
+ dynamicVariables: [],
3081
+ status: 'Running',
3082
+ isExecuting: false,
3083
+ faultCount: 0,
3084
+ startedAt: now,
3085
+ completedAt: null,
3086
+ tag: null
3087
+ }] : [],
3088
+ input: request.input || {},
3089
+ output: {},
3090
+ properties: {},
3091
+ createdAt: now,
3092
+ updatedAt: now,
3093
+ finishedAt: null
2974
3094
  };
2975
- // Find next task based on outcomes and outcomeConnections
2976
- let nextTask = null;
2977
- let nextStepId = undefined;
2978
- const outcome = Object.keys(executionResult.outcomes)[0];
2979
- if (currentActivity && currentActivity.outcomeConnections) {
2980
- // Find connection for this outcome
2981
- const connection = currentActivity.outcomeConnections.find((conn) => conn.outcome === outcome);
2982
- if (connection && connection.targetNodeId) {
2983
- const targetActivity = this.findActivityInWorkflow(workflow.root, connection.targetNodeId);
2984
- if (targetActivity) {
2985
- nextStepId = targetActivity.id || connection.targetNodeId;
2986
- nextTask = this.createTaskFromStep(targetActivity, state);
2987
- }
3095
+ // Create workflow instance
3096
+ const instance = {
3097
+ $schema: 'https://elsaworkflows.io/schemas/workflow-instance/v3.0.0/schema.json',
3098
+ id: instanceId,
3099
+ definitionId: workflow.definitionId,
3100
+ definitionVersionId: workflow.id,
3101
+ version: workflow.version,
3102
+ parentWorkflowInstanceId: null,
3103
+ workflowState,
3104
+ status: 'Running',
3105
+ subStatus: 'Executing',
3106
+ correlationId: null,
3107
+ name: workflow.name || null,
3108
+ incidentCount: 0,
3109
+ createdAt: now,
3110
+ updatedAt: now,
3111
+ finishedAt: null
3112
+ };
3113
+ // Store instance in IndexedDB
3114
+ await this.db.instances.add(instance, instance.id);
3115
+ // Convert to execution state for response
3116
+ let state = this.instanceToExecutionState(instance);
3117
+ // 🎯 KEY LOGIC: Execute all backend activities until we reach a frontend activity
3118
+ let currentActivity = firstActivity;
3119
+ let executionCount = 0;
3120
+ const maxExecutions = 100; // Prevent infinite loops
3121
+ while (currentActivity && executionCount < maxExecutions) {
3122
+ executionCount++;
3123
+ // Map activity type to ACoreX format
3124
+ let activityType = currentActivity.type;
3125
+ if (activityType.startsWith('Elsa.')) {
3126
+ let type = activityType.replace(/^Elsa\./, '');
3127
+ type = type.replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, '');
3128
+ activityType = `workflow-activity:${type}`;
2988
3129
  }
3130
+ // Determine execution mode
3131
+ const executionMode = this.determineExecutionMode(activityType, currentActivity);
3132
+ // If frontend activity → stop and return as pendingTask
3133
+ if (executionMode === 'frontend') {
3134
+ const pendingTask = this.createTaskFromActivity(currentActivity, state);
3135
+ // Update state to suspended (waiting for frontend)
3136
+ state = {
3137
+ ...state,
3138
+ status: 'suspended',
3139
+ currentStepId: currentActivity.id,
3140
+ };
3141
+ await this.updateInstanceFromExecutionState(instanceId, state);
3142
+ return {
3143
+ executionId: instanceId,
3144
+ state,
3145
+ pendingTask
3146
+ };
3147
+ }
3148
+ // Backend activity → execute it
3149
+ console.log(`[WorkflowExecutionService] Executing backend activity '${currentActivity.name || currentActivity.id}' (${activityType})`);
3150
+ const executionResult = await this.executeBackendActivityLocally(currentActivity, { ...state.variables, ...state.input }, state);
3151
+ // Update variables with output
3152
+ state = {
3153
+ ...state,
3154
+ variables: {
3155
+ ...state.variables,
3156
+ ...executionResult.output
3157
+ },
3158
+ currentStepId: currentActivity.id,
3159
+ lastUpdated: new Date()
3160
+ };
3161
+ // Find next activity based on outcome
3162
+ const outcome = Object.keys(executionResult.outcomes)[0] || 'Done';
3163
+ const nextConnection = connections.find((conn) => conn.source.activity === currentActivity.id &&
3164
+ (conn.source.port === outcome || (!conn.source.port && outcome === 'Done')));
3165
+ if (!nextConnection) {
3166
+ // No next activity → workflow completed
3167
+ state = {
3168
+ ...state,
3169
+ status: 'completed',
3170
+ currentStepId: undefined,
3171
+ output: state.variables
3172
+ };
3173
+ await this.updateInstanceFromExecutionState(instanceId, state);
3174
+ return {
3175
+ executionId: instanceId,
3176
+ state,
3177
+ pendingTask: null
3178
+ };
3179
+ }
3180
+ // Find next activity
3181
+ currentActivity = this.findActivityInFlowchart(flowchart, nextConnection.target.activity);
2989
3182
  }
2990
- // Update state with next step ID
2991
- const updatedState = {
3183
+ // If we exit loop without frontend activity, workflow is complete
3184
+ state = {
2992
3185
  ...state,
2993
- status: nextStepId ? 'running' : 'completed', // If no next step, workflow is completed
2994
- currentStepId: nextStepId, // Set next step ID to continue workflow
2995
- variables: updatedVariables,
2996
- lastUpdated: new Date(),
2997
- };
2998
- // Update nextTask with updated state
2999
- if (nextTask && nextStepId) {
3000
- nextTask = this.createTaskFromStep(this.findActivityInWorkflow(workflow.root, nextStepId), updatedState);
3001
- }
3002
- // Save to IndexedDB (convert Date to ISO string)
3003
- const stateToStore = {
3004
- ...updatedState,
3005
- lastUpdated: updatedState.lastUpdated.toISOString(),
3186
+ status: 'completed',
3187
+ currentStepId: undefined,
3188
+ output: state.variables
3006
3189
  };
3007
- await this.db.executions.update(state.executionId, stateToStore);
3190
+ await this.updateInstanceFromExecutionState(instanceId, state);
3008
3191
  return {
3009
- output: executionResult.output,
3010
- outcomes: executionResult.outcomes,
3011
- nextTask,
3012
- state: updatedState,
3192
+ executionId: instanceId,
3193
+ state,
3194
+ pendingTask: null
3013
3195
  };
3014
3196
  }
3015
3197
  /**
3016
- * Find activity in workflow tree recursively.
3198
+ * Find activity in Flowchart by ID.
3017
3199
  */
3018
- findActivityInWorkflow(activity, activityId) {
3019
- const activityAny = activity;
3020
- if (activityAny.id === activityId) {
3021
- return activity;
3022
- }
3023
- if (activityAny.children && Array.isArray(activityAny.children)) {
3024
- for (const child of activityAny.children) {
3025
- const found = this.findActivityInWorkflow(child, activityId);
3026
- if (found) {
3027
- return found;
3028
- }
3029
- }
3030
- }
3031
- return null;
3200
+ findActivityInFlowchart(flowchart, activityId) {
3201
+ const activities = flowchart.activities || [];
3202
+ return activities.find(a => a.id === activityId) || null;
3032
3203
  }
3033
3204
  /**
3034
3205
  * Resume a suspended workflow execution.
3206
+ *
3207
+ * After frontend completes its task:
3208
+ * 1. Validates taskToken
3209
+ * 2. Finds next activity based on outcome
3210
+ * 3. Executes ALL backend activities in sequence
3211
+ * 4. Stops at first frontend activity and returns it as pendingTask
3035
3212
  */
3036
3213
  async resumeExecution(request) {
3037
3214
  // Get current state
3038
- const state = await this.getExecutionState({
3215
+ let state = await this.getExecutionState({
3039
3216
  executionId: request.executionId,
3040
3217
  });
3041
3218
  if (!state) {
@@ -3044,78 +3221,139 @@ class AXCWorkflowExecutionService {
3044
3221
  if (state.status !== 'suspended') {
3045
3222
  throw new Error(`Cannot resume workflow with status: ${state.status}. Expected: suspended`);
3046
3223
  }
3047
- // Find next step based on outcomeConnections and actual outcome
3224
+ // TODO: Validate taskToken here for security
3225
+ // For now, just verify stepId matches
3226
+ if (state.currentStepId !== request.stepId) {
3227
+ throw new Error(`Step mismatch: expected '${state.currentStepId}', got '${request.stepId}'`);
3228
+ }
3229
+ // Get workflow definition
3048
3230
  const workflowResponse = await this.getWorkflowDefinition({
3049
3231
  workflowId: state.workflowId
3050
3232
  });
3051
3233
  const workflow = workflowResponse.workflow;
3052
- // Find current step in workflow
3053
- const currentStep = this.findActivityInWorkflow(workflow.root, request.stepId);
3054
- let nextTask = null;
3055
- let nextStepId = undefined;
3056
- if (currentStep && currentStep.outcomeConnections) {
3057
- // Find connection for the outcome
3058
- const connection = currentStep.outcomeConnections.find((conn) => conn.outcome === request.outcome);
3059
- if (connection && connection.targetNodeId) {
3060
- const targetStep = this.findActivityInWorkflow(workflow.root, connection.targetNodeId);
3061
- if (targetStep) {
3062
- nextStepId = targetStep.id || connection.targetNodeId;
3063
- nextTask = this.createTaskFromStep(targetStep, state);
3064
- }
3065
- }
3066
- }
3067
- // Update state with outcome and user input
3068
- const updatedVariables = {
3069
- ...state.variables,
3070
- [`${request.stepId}_outcome`]: request.outcome,
3071
- [`${request.stepId}_userInput`]: request.userInput || {},
3072
- };
3073
- const updatedState = {
3234
+ const connections = workflow.root.connections || [];
3235
+ // Update state with frontend activity outcome and user input
3236
+ state = {
3074
3237
  ...state,
3075
- status: nextStepId ? 'running' : 'completed', // If no next step, workflow is completed
3076
- currentStepId: nextStepId, // Set next step ID to continue workflow
3077
- variables: updatedVariables,
3078
- lastUpdated: new Date(),
3079
- };
3080
- // Save to IndexedDB (convert Date to ISO string)
3081
- const stateToStore = {
3082
- ...updatedState,
3083
- lastUpdated: updatedState.lastUpdated.toISOString(),
3238
+ variables: {
3239
+ ...state.variables,
3240
+ [`${request.stepId}_outcome`]: request.outcome,
3241
+ [`${request.stepId}_userInput`]: request.userInput || {},
3242
+ },
3243
+ lastUpdated: new Date()
3084
3244
  };
3085
- await this.db.executions.update(state.executionId, stateToStore);
3086
- // Update nextTask with updated state
3087
- if (nextTask && nextStepId) {
3088
- nextTask = this.createTaskFromStep(this.findActivityInWorkflow(workflow.root, nextStepId), updatedState);
3245
+ // Find next activity based on outcome from frontend
3246
+ const nextConnection = connections.find((conn) => conn.source.activity === request.stepId &&
3247
+ (conn.source.port === request.outcome || (!conn.source.port && request.outcome === 'Done')));
3248
+ if (!nextConnection) {
3249
+ // No next activity → workflow completed
3250
+ state = {
3251
+ ...state,
3252
+ status: 'completed',
3253
+ currentStepId: undefined,
3254
+ output: state.variables
3255
+ };
3256
+ await this.updateInstanceFromExecutionState(request.executionId, state);
3257
+ return {
3258
+ output: { outcome: request.outcome, userInput: request.userInput },
3259
+ outcomes: { [request.outcome]: true },
3260
+ nextTask: null,
3261
+ state
3262
+ };
3089
3263
  }
3090
- // Output based on outcome
3091
- const output = {
3092
- outcome: request.outcome,
3093
- stepId: request.stepId,
3094
- userInput: request.userInput,
3095
- resumedAt: new Date().toISOString(),
3264
+ // 🎯 KEY LOGIC: Execute all backend activities until we reach next frontend activity
3265
+ let currentActivity = this.findActivityInFlowchart(workflow.root, nextConnection.target.activity);
3266
+ let executionCount = 0;
3267
+ const maxExecutions = 100;
3268
+ while (currentActivity && executionCount < maxExecutions) {
3269
+ executionCount++;
3270
+ // Map activity type
3271
+ let activityType = currentActivity.type;
3272
+ if (activityType.startsWith('Elsa.')) {
3273
+ let type = activityType.replace(/^Elsa\./, '');
3274
+ type = type.replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, '');
3275
+ activityType = `workflow-activity:${type}`;
3276
+ }
3277
+ // Determine execution mode
3278
+ const executionMode = this.determineExecutionMode(activityType, currentActivity);
3279
+ // If frontend activity → stop and return as pendingTask
3280
+ if (executionMode === 'frontend') {
3281
+ const pendingTask = this.createTaskFromActivity(currentActivity, state);
3282
+ state = {
3283
+ ...state,
3284
+ status: 'suspended',
3285
+ currentStepId: currentActivity.id,
3286
+ };
3287
+ await this.updateInstanceFromExecutionState(request.executionId, state);
3288
+ return {
3289
+ output: { outcome: request.outcome, userInput: request.userInput },
3290
+ outcomes: { [request.outcome]: true },
3291
+ nextTask: pendingTask,
3292
+ state
3293
+ };
3294
+ }
3295
+ // Backend activity → execute it
3296
+ console.log(`[WorkflowExecutionService] Executing backend activity '${currentActivity.name || currentActivity.id}' (${activityType})`);
3297
+ const executionResult = await this.executeBackendActivityLocally(currentActivity, { ...state.variables, ...state.input }, state);
3298
+ // Update variables with output
3299
+ state = {
3300
+ ...state,
3301
+ variables: {
3302
+ ...state.variables,
3303
+ ...executionResult.output
3304
+ },
3305
+ currentStepId: currentActivity.id,
3306
+ lastUpdated: new Date()
3307
+ };
3308
+ // Find next activity based on outcome
3309
+ const outcome = Object.keys(executionResult.outcomes)[0] || 'Done';
3310
+ const nextConn = connections.find((conn) => conn.source.activity === currentActivity.id &&
3311
+ (conn.source.port === outcome || (!conn.source.port && outcome === 'Done')));
3312
+ if (!nextConn) {
3313
+ // No next activity → workflow completed
3314
+ state = {
3315
+ ...state,
3316
+ status: 'completed',
3317
+ currentStepId: undefined,
3318
+ output: state.variables
3319
+ };
3320
+ await this.updateInstanceFromExecutionState(request.executionId, state);
3321
+ return {
3322
+ output: state.variables,
3323
+ outcomes: { Done: true },
3324
+ nextTask: null,
3325
+ state
3326
+ };
3327
+ }
3328
+ // Find next activity
3329
+ currentActivity = this.findActivityInFlowchart(workflow.root, nextConn.target.activity);
3330
+ }
3331
+ // If we exit loop, workflow is complete
3332
+ state = {
3333
+ ...state,
3334
+ status: 'completed',
3335
+ currentStepId: undefined,
3336
+ output: state.variables
3096
3337
  };
3338
+ await this.updateInstanceFromExecutionState(request.executionId, state);
3097
3339
  return {
3098
- output,
3099
- outcomes: {
3100
- [request.outcome]: true,
3101
- },
3102
- nextTask, // Next task from outcomeConnections
3103
- state: updatedState,
3340
+ output: state.variables,
3341
+ outcomes: { Done: true },
3342
+ nextTask: null,
3343
+ state
3104
3344
  };
3105
3345
  }
3106
3346
  /**
3107
3347
  * Get current workflow execution state.
3108
3348
  */
3109
3349
  async getExecutionState(request) {
3110
- const state = await this.db.executions.get(request.executionId);
3111
- if (!state) {
3350
+ // Get instance from IndexedDB
3351
+ const instance = await this.getInstance(request.executionId);
3352
+ if (!instance) {
3112
3353
  throw new Error(`Workflow execution not found: ${request.executionId}`);
3113
3354
  }
3114
- // Convert Date string back to Date object (IndexedDB stores as ISO string)
3115
- return {
3116
- ...state,
3117
- lastUpdated: new Date(state.lastUpdated),
3118
- };
3355
+ // Convert instance to execution state
3356
+ return this.instanceToExecutionState(instance);
3119
3357
  }
3120
3358
  /**
3121
3359
  * Get workflow definition by ID.
@@ -3131,10 +3369,28 @@ class AXCWorkflowExecutionService {
3131
3369
  const storedWorkflow = localStorage.getItem(`workflow:${request.workflowId}`);
3132
3370
  if (storedWorkflow) {
3133
3371
  try {
3134
- const elsaDefinition = JSON.parse(storedWorkflow);
3135
- // Convert Elsa Workflow Definition v3.0.0 to AXPWorkflowEngine format
3136
- const workflow = this.convertElsaToWorkflowEngine(elsaDefinition);
3137
- return { workflow };
3372
+ const workflowDefinition = JSON.parse(storedWorkflow);
3373
+ // Validate format
3374
+ if (workflowDefinition.root && workflowDefinition.root.type === 'Elsa.Flowchart') {
3375
+ return { workflow: workflowDefinition };
3376
+ }
3377
+ // If stored in materializerContext.stringData, parse it
3378
+ if (workflowDefinition.materializerContext?.stringData) {
3379
+ try {
3380
+ const rootFlowchart = JSON.parse(workflowDefinition.materializerContext.stringData);
3381
+ if (rootFlowchart.type === 'Elsa.Flowchart') {
3382
+ return {
3383
+ workflow: {
3384
+ ...workflowDefinition,
3385
+ root: rootFlowchart
3386
+ }
3387
+ };
3388
+ }
3389
+ }
3390
+ catch (error) {
3391
+ console.warn('Failed to parse stringData from materializerContext:', error);
3392
+ }
3393
+ }
3138
3394
  }
3139
3395
  catch (error) {
3140
3396
  console.warn(`Failed to parse stored workflow ${request.workflowId}:`, error);
@@ -3142,181 +3398,39 @@ class AXCWorkflowExecutionService {
3142
3398
  }
3143
3399
  // If not found in localStorage, return a default mock workflow
3144
3400
  // In production, this would be an HTTP call to backend
3401
+ const now = new Date().toISOString();
3145
3402
  const defaultWorkflow = {
3403
+ $schema: 'https://elsaworkflows.io/schemas/workflow-definition/v3.0.0/schema.json',
3146
3404
  id: request.workflowId,
3147
- name: `Workflow ${request.workflowId}`,
3405
+ definitionId: request.workflowId,
3406
+ createdAt: now,
3148
3407
  version: 1,
3149
- root: {
3150
- type: 'workflow-activity:sequence',
3151
- name: 'Root Sequence',
3152
- execute: async () => ({ output: undefined, outcomes: { Done: true } })
3408
+ isLatest: true,
3409
+ isPublished: false,
3410
+ isReadonly: false,
3411
+ isSystem: false,
3412
+ name: `Workflow ${request.workflowId}`,
3413
+ description: 'Default mock workflow',
3414
+ variables: [],
3415
+ inputs: [],
3416
+ outputs: [],
3417
+ outcomes: ['Done'],
3418
+ customProperties: {},
3419
+ options: {
3420
+ usableAsActivity: false,
3421
+ autoUpdateConsumingWorkflows: false
3153
3422
  },
3154
- activities: []
3155
- };
3156
- return { workflow: defaultWorkflow };
3157
- }
3158
- /**
3159
- * Convert Elsa Workflow Definition v3.0.0 to AXPWorkflowEngine format
3160
- * https://elsaworkflows.io/schemas/workflow-definition/v3.0.0/schema.json
3161
- */
3162
- convertElsaToWorkflowEngine(elsaDefinition) {
3163
- // Extract root activity from Elsa format
3164
- let rootActivity;
3165
- if (elsaDefinition.root) {
3166
- // Root activity is directly available
3167
- rootActivity = elsaDefinition.root;
3168
- }
3169
- else if (elsaDefinition.materializerContext?.stringData) {
3170
- // Root activity is stored in materializerContext.stringData
3171
- try {
3172
- rootActivity = JSON.parse(elsaDefinition.materializerContext.stringData);
3173
- }
3174
- catch (error) {
3175
- console.warn('Failed to parse stringData from materializerContext:', error);
3176
- // Fallback to default
3177
- rootActivity = {
3178
- type: 'workflow-activity:sequence',
3179
- name: 'Root Sequence'
3180
- };
3423
+ root: {
3424
+ id: 'root-flowchart',
3425
+ nodeId: 'root-flowchart',
3426
+ type: 'Elsa.Flowchart',
3427
+ version: 1,
3428
+ activities: [],
3429
+ connections: [],
3430
+ variables: []
3181
3431
  }
3182
- }
3183
- else {
3184
- // Fallback to default
3185
- rootActivity = {
3186
- type: 'workflow-activity:sequence',
3187
- name: 'Root Sequence'
3188
- };
3189
- }
3190
- // Convert to AXPWorkflowEngine format
3191
- const workflow = {
3192
- id: elsaDefinition.id || elsaDefinition.definitionId || 'unknown',
3193
- name: elsaDefinition.name || 'Untitled Workflow',
3194
- description: elsaDefinition.description,
3195
- version: elsaDefinition.version || 1,
3196
- root: rootActivity,
3197
- activities: this.extractActivities(rootActivity)
3198
3432
  };
3199
- return workflow;
3200
- }
3201
- /**
3202
- * Extract all activities from root activity recursively
3203
- */
3204
- extractActivities(activity) {
3205
- const activities = [];
3206
- if (!activity) {
3207
- return activities;
3208
- }
3209
- // Add current activity
3210
- activities.push(activity);
3211
- // Extract from children (for sequence, parallel, etc.)
3212
- if (activity.children && Array.isArray(activity.children)) {
3213
- activity.children.forEach((child) => {
3214
- activities.push(...this.extractActivities(child));
3215
- });
3216
- }
3217
- // Extract from then/else (for if activity)
3218
- if (activity.then) {
3219
- activities.push(...this.extractActivities(activity.then));
3220
- }
3221
- if (activity.else) {
3222
- activities.push(...this.extractActivities(activity.else));
3223
- }
3224
- // Extract from try/catch/finally (for try-catch activity)
3225
- if (activity.try) {
3226
- activities.push(...this.extractActivities(activity.try));
3227
- }
3228
- if (activity.catch) {
3229
- activities.push(...this.extractActivities(activity.catch));
3230
- }
3231
- if (activity.finally) {
3232
- activities.push(...this.extractActivities(activity.finally));
3233
- }
3234
- // Extract from branches (for parallel activity)
3235
- if (activity.branches && Array.isArray(activity.branches)) {
3236
- activity.branches.forEach((branch) => {
3237
- activities.push(...this.extractActivities(branch));
3238
- });
3239
- }
3240
- return activities;
3241
- }
3242
- /**
3243
- * Execute current step from execution state.
3244
- *
3245
- * Backend handles everything: gets state, workflow definition, finds step, determines nextStep.
3246
- */
3247
- async executeCurrentStep(request) {
3248
- // Get current state
3249
- const state = await this.getExecutionState({
3250
- executionId: request.executionId,
3251
- });
3252
- if (!state.currentStepId) {
3253
- throw new Error(`No current step defined for execution: ${request.executionId}`);
3254
- }
3255
- // Get workflow definition
3256
- const workflowResponse = await this.getWorkflowDefinition({
3257
- workflowId: state.workflowId
3258
- });
3259
- if (!workflowResponse.workflow) {
3260
- throw new Error(`Workflow definition not found: ${state.workflowId}`);
3261
- }
3262
- // Find current step in workflow
3263
- const currentStep = this.findActivityInWorkflow(workflowResponse.workflow.root, state.currentStepId);
3264
- if (!currentStep) {
3265
- throw new Error(`Step '${state.currentStepId}' not found in workflow '${state.workflowId}'`);
3266
- }
3267
- // Determine execution mode from activity definition or descriptor
3268
- const stepAny = currentStep;
3269
- const executionMode = this.determineExecutionMode(stepAny.type, stepAny);
3270
- const isBackendActivity = executionMode === 'backend' || executionMode === 'both';
3271
- if (isBackendActivity) {
3272
- // Execute backend activity
3273
- const backendResponse = await this.executeBackendActivity({
3274
- workflowId: state.workflowId,
3275
- executionId: request.executionId,
3276
- activityType: stepAny.type,
3277
- activityId: state.currentStepId,
3278
- properties: stepAny.properties || {},
3279
- workflowState: {
3280
- variables: state.variables,
3281
- input: state.input
3282
- }
3283
- });
3284
- return {
3285
- output: backendResponse.output,
3286
- outcomes: backendResponse.outcomes,
3287
- nextTask: backendResponse.nextTask || null,
3288
- state: backendResponse.state
3289
- };
3290
- }
3291
- else {
3292
- // Frontend activity - return current task for frontend to execute
3293
- // The nextTask should be the CURRENT activity (frontend will execute it)
3294
- // After frontend executes, it will call resumeExecution with outcome
3295
- // Create task for current step (frontend will execute this)
3296
- const currentTask = this.createTaskFromStep(currentStep, state);
3297
- // Update state to indicate step is suspended (waiting for frontend execution)
3298
- const updatedState = {
3299
- ...state,
3300
- status: 'suspended', // Frontend activities suspend the workflow
3301
- lastUpdated: new Date()
3302
- };
3303
- // Save to IndexedDB
3304
- const stateToStore = {
3305
- ...updatedState,
3306
- lastUpdated: updatedState.lastUpdated.toISOString(),
3307
- };
3308
- await this.db.executions.update(state.executionId, stateToStore);
3309
- return {
3310
- output: {
3311
- stepId: state.currentStepId,
3312
- stepType: stepAny.type,
3313
- properties: stepAny.properties || {}
3314
- },
3315
- outcomes: {},
3316
- nextTask: currentTask, // Return current task so frontend can execute it
3317
- state: updatedState
3318
- };
3319
- }
3433
+ return { workflow: defaultWorkflow };
3320
3434
  }
3321
3435
  //#region ---- Task-Based Helper Methods ----
3322
3436
  /**
@@ -3327,19 +3441,21 @@ class AXCWorkflowExecutionService {
3327
3441
  return `${executionId}:${activityId}:${Date.now()}`;
3328
3442
  }
3329
3443
  /**
3330
- * Determine execution mode for an activity from its descriptor.
3444
+ * Determine execution mode for an activity.
3331
3445
  *
3332
- * First checks if activity has executionMode in its definition (from workflow JSON).
3333
- * If not, falls back to ActivityDescriptor from ActivityProviderService.
3446
+ * Priority (highest to lowest):
3447
+ * 1. Activity instance's executionMode (from AXPActivity in workflow definition)
3448
+ * 2. ActivityDescriptor's executionMode (from ActivityProviderService)
3449
+ * 3. Default: 'frontend'
3334
3450
  *
3335
3451
  * @param activityType - Activity type (e.g., 'workflow-activity:write-line')
3336
- * @param activityDefinition - Activity definition from workflow (may contain executionMode)
3452
+ * @param activity - Activity from workflow definition (AXPActivity)
3337
3453
  * @returns Execution mode: 'frontend', 'backend', or 'both'
3338
3454
  */
3339
- determineExecutionMode(activityType, activityDefinition) {
3340
- // 1. Check if executionMode is defined in activity definition (from workflow JSON/database)
3341
- if (activityDefinition?.executionMode) {
3342
- return activityDefinition.executionMode;
3455
+ determineExecutionMode(activityType, activity) {
3456
+ // 1. Check if executionMode is explicitly set in activity instance (highest priority)
3457
+ if (activity?.executionMode) {
3458
+ return activity.executionMode;
3343
3459
  }
3344
3460
  // 2. Check ActivityDescriptor from ActivityProviderService
3345
3461
  const descriptor = this.activityProviderService.getDescriptor(activityType);
@@ -3350,39 +3466,117 @@ class AXCWorkflowExecutionService {
3350
3466
  return 'frontend';
3351
3467
  }
3352
3468
  /**
3353
- * Create a task from a workflow step.
3469
+ * Create a task from a workflow activity.
3354
3470
  * Inspired by Temporal's Activity Task and Elsa's Bookmark pattern.
3355
3471
  */
3356
- createTaskFromStep(step, state) {
3357
- const stepAny = step;
3358
- // Get executionMode from activity definition or descriptor
3359
- const executionMode = this.determineExecutionMode(step.type, stepAny);
3472
+ createTaskFromActivity(activity, state) {
3473
+ // Extract properties from activity
3474
+ // Activities have properties as AXPInputValue objects or primitives
3475
+ const properties = {};
3476
+ // Iterate through all properties of the activity
3477
+ Object.keys(activity).forEach(key => {
3478
+ // Skip standard Elsa fields
3479
+ if (['id', 'nodeId', 'name', 'type', 'version', 'customProperties', 'metadata'].includes(key)) {
3480
+ return;
3481
+ }
3482
+ const value = activity[key];
3483
+ // Handle AXPInputValue format
3484
+ if (value && typeof value === 'object' && 'typeName' in value && 'expression' in value) {
3485
+ // It's an AXPInputValue - extract the expression value
3486
+ if (value.expression && value.expression.value !== undefined) {
3487
+ properties[key] = value.expression.value;
3488
+ }
3489
+ else {
3490
+ properties[key] = null;
3491
+ }
3492
+ }
3493
+ else {
3494
+ // Direct value
3495
+ properties[key] = value;
3496
+ }
3497
+ });
3498
+ // Map activity type to ACoreX activity type
3499
+ // Example: "Elsa.WriteLine" -> "workflow-activity:write-line"
3500
+ let activityType = activity.type;
3501
+ if (activityType.startsWith('Elsa.')) {
3502
+ let type = activityType.replace(/^Elsa\./, '');
3503
+ // Convert PascalCase to kebab-case
3504
+ type = type.replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, '');
3505
+ activityType = `workflow-activity:${type}`;
3506
+ }
3507
+ // Get executionMode from activity descriptor
3508
+ const executionMode = this.determineExecutionMode(activityType, activity);
3360
3509
  return {
3361
- taskToken: this.generateTaskToken(state.executionId, stepAny.id),
3362
- activityId: stepAny.id,
3363
- activityType: step.type,
3364
- activityName: step.name,
3510
+ taskToken: this.generateTaskToken(state.executionId, activity.id),
3511
+ activityId: activity.id,
3512
+ activityType,
3513
+ activityName: activity.name || undefined,
3365
3514
  executionMode,
3366
- input: (executionMode === 'frontend' || executionMode === 'both') ? stepAny.properties : undefined,
3367
- config: (executionMode === 'frontend' || executionMode === 'both') ? stepAny.properties : undefined
3515
+ input: (executionMode === 'frontend' || executionMode === 'both') ? properties : undefined,
3516
+ config: (executionMode === 'frontend' || executionMode === 'both') ? properties : undefined
3368
3517
  };
3369
3518
  }
3370
3519
  //#endregion
3371
3520
  //#region ---- Backend Activity Executors ----
3372
3521
  /**
3373
- * Execute backend activities locally in mock service.
3374
- * In production, these would be executed by the actual backend.
3522
+ * Execute backend activities locally using CommandBus.
3523
+ *
3524
+ * Backend activities are registered as Commands and executed via CommandService.
3525
+ * This provides a unified execution channel for all activities.
3375
3526
  */
3376
3527
  async executeBackendActivityLocally(activity, input, state) {
3377
- switch (activity.type) {
3528
+ // Extract properties from activity
3529
+ const properties = {};
3530
+ Object.keys(activity).forEach(key => {
3531
+ if (['id', 'nodeId', 'name', 'type', 'version', 'customProperties', 'metadata', 'executionMode'].includes(key)) {
3532
+ return;
3533
+ }
3534
+ const value = activity[key];
3535
+ if (value && typeof value === 'object' && 'typeName' in value && 'expression' in value) {
3536
+ if (value.expression && value.expression.value !== undefined) {
3537
+ properties[key] = value.expression.value;
3538
+ }
3539
+ else {
3540
+ properties[key] = null;
3541
+ }
3542
+ }
3543
+ else {
3544
+ properties[key] = value;
3545
+ }
3546
+ });
3547
+ // Map activity type to ACoreX activity type
3548
+ let activityType = activity.type;
3549
+ if (activityType.startsWith('Elsa.')) {
3550
+ let type = activityType.replace(/^Elsa\./, '');
3551
+ type = type.replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, '');
3552
+ activityType = `workflow-activity:${type}`;
3553
+ }
3554
+ // Check if activity is registered as a Command
3555
+ if (this.commandService.exists(activityType)) {
3556
+ console.log(`[WorkflowExecutionService] Executing backend activity '${activityType}' via CommandBus`);
3557
+ try {
3558
+ // Execute via CommandBus
3559
+ const result = await this.commandService.execute(activityType, properties);
3560
+ return {
3561
+ output: result?.output || result,
3562
+ outcomes: result?.outcomes || { Done: true }
3563
+ };
3564
+ }
3565
+ catch (error) {
3566
+ console.error(`[WorkflowExecutionService] Backend activity '${activityType}' failed:`, error);
3567
+ return {
3568
+ output: { error: error.message || 'Unknown error' },
3569
+ outcomes: { Failed: true }
3570
+ };
3571
+ }
3572
+ }
3573
+ // Fallback: Handle built-in activities that aren't Commands yet
3574
+ console.warn(`[WorkflowExecutionService] Activity '${activityType}' not registered as Command, using fallback`);
3575
+ switch (activityType) {
3378
3576
  case 'workflow-activity:set-variable':
3379
- return this.executeSetVariable(activity, input);
3380
- case 'workflow-activity:execute-command':
3381
- return this.executeCommandMock(activity, input);
3382
- case 'workflow-activity:execute-query':
3383
- return this.executeQueryMock(activity, input);
3577
+ return this.executeSetVariable({ type: activityType, properties }, input);
3384
3578
  case 'workflow-activity:http-request':
3385
- return this.executeHttpRequest(activity, input);
3579
+ return this.executeHttpRequest({ type: activityType, properties }, input);
3386
3580
  default:
3387
3581
  return { output: null, outcomes: { Done: true } };
3388
3582
  }
@@ -3398,42 +3592,6 @@ class AXCWorkflowExecutionService {
3398
3592
  outcomes: { Done: true }
3399
3593
  };
3400
3594
  }
3401
- /**
3402
- * Execute command mock - simulates backend command execution.
3403
- */
3404
- async executeCommandMock(activity, input) {
3405
- // Simulate delay for backend processing
3406
- await new Promise(resolve => setTimeout(resolve, 500));
3407
- return {
3408
- output: {
3409
- commandKey: activity.properties?.commandKey,
3410
- success: true,
3411
- result: {
3412
- id: 'mock-' + Date.now(),
3413
- timestamp: new Date().toISOString()
3414
- }
3415
- },
3416
- outcomes: { Done: true }
3417
- };
3418
- }
3419
- /**
3420
- * Execute query mock - simulates backend query execution.
3421
- */
3422
- async executeQueryMock(activity, input) {
3423
- // Simulate delay for database query
3424
- await new Promise(resolve => setTimeout(resolve, 300));
3425
- return {
3426
- output: {
3427
- queryKey: activity.properties?.queryKey,
3428
- data: [
3429
- { id: 1, name: 'Mock Item 1', createdAt: new Date().toISOString() },
3430
- { id: 2, name: 'Mock Item 2', createdAt: new Date().toISOString() }
3431
- ],
3432
- count: 2
3433
- },
3434
- outcomes: { Done: true }
3435
- };
3436
- }
3437
3595
  /**
3438
3596
  * Execute HTTP request - makes real HTTP call.
3439
3597
  * Supports different HTTP methods and handles timeouts.
@@ -3499,6 +3657,117 @@ class AXCWorkflowExecutionService {
3499
3657
  };
3500
3658
  }
3501
3659
  }
3660
+ //#endregion
3661
+ //#region ---- Instance Management ----
3662
+ /**
3663
+ * Convert workflow instance to execution state (for backward compatibility).
3664
+ */
3665
+ instanceToExecutionState(instance) {
3666
+ const state = instance.workflowState;
3667
+ // Find current activity from execution contexts
3668
+ const currentContext = state.activityExecutionContexts.find(ctx => ctx.status === 'Running' && !ctx.completedAt);
3669
+ // Map status
3670
+ let status = 'running';
3671
+ if (instance.status === 'Finished') {
3672
+ if (instance.subStatus === 'Faulted') {
3673
+ status = 'error';
3674
+ }
3675
+ else {
3676
+ status = 'completed';
3677
+ }
3678
+ }
3679
+ else if (instance.subStatus === 'Suspended') {
3680
+ status = 'suspended';
3681
+ }
3682
+ return {
3683
+ executionId: instance.id,
3684
+ workflowId: instance.definitionId,
3685
+ status,
3686
+ currentStepId: currentContext?.scheduledActivityNodeId,
3687
+ variables: state.properties || {},
3688
+ input: state.input || {},
3689
+ output: state.output || {},
3690
+ lastUpdated: new Date(instance.updatedAt)
3691
+ };
3692
+ }
3693
+ /**
3694
+ * Update execution state in instance and save to IndexedDB.
3695
+ */
3696
+ async updateInstanceFromExecutionState(executionId, executionState) {
3697
+ const instance = await this.getInstance(executionId);
3698
+ if (!instance) {
3699
+ throw new Error(`Workflow instance not found: ${executionId}`);
3700
+ }
3701
+ // Update instance from execution state
3702
+ const now = new Date().toISOString();
3703
+ // Map execution state status to instance status
3704
+ let status = 'Running';
3705
+ let subStatus = 'Executing';
3706
+ if (executionState.status === 'completed') {
3707
+ status = 'Finished';
3708
+ subStatus = 'Finished';
3709
+ instance.finishedAt = now;
3710
+ }
3711
+ else if (executionState.status === 'error') {
3712
+ status = 'Finished';
3713
+ subStatus = 'Faulted';
3714
+ instance.finishedAt = now;
3715
+ }
3716
+ else if (executionState.status === 'suspended') {
3717
+ subStatus = 'Suspended';
3718
+ }
3719
+ instance.status = status;
3720
+ instance.subStatus = subStatus;
3721
+ instance.updatedAt = now;
3722
+ // Update workflow state
3723
+ instance.workflowState.status = status;
3724
+ instance.workflowState.subStatus = subStatus;
3725
+ instance.workflowState.input = executionState.input || {};
3726
+ instance.workflowState.output = executionState.output || {};
3727
+ instance.workflowState.properties = executionState.variables || {};
3728
+ instance.workflowState.updatedAt = now;
3729
+ if (executionState.status === 'completed' || executionState.status === 'error') {
3730
+ instance.workflowState.finishedAt = now;
3731
+ }
3732
+ // Update activity execution context if currentStepId changed
3733
+ if (executionState.currentStepId) {
3734
+ const existingContext = instance.workflowState.activityExecutionContexts.find(ctx => ctx.scheduledActivityNodeId === executionState.currentStepId);
3735
+ if (!existingContext) {
3736
+ // Add new context
3737
+ instance.workflowState.activityExecutionContexts.push({
3738
+ id: `ctx-${executionState.currentStepId}`,
3739
+ parentContextId: null,
3740
+ scheduledActivityNodeId: executionState.currentStepId,
3741
+ ownerActivityNodeId: null,
3742
+ properties: {},
3743
+ activityState: null,
3744
+ dynamicVariables: [],
3745
+ status: 'Running',
3746
+ isExecuting: false,
3747
+ faultCount: 0,
3748
+ startedAt: now,
3749
+ completedAt: null,
3750
+ tag: null
3751
+ });
3752
+ }
3753
+ }
3754
+ // Save to IndexedDB
3755
+ await this.updateInstance(instance);
3756
+ return instance;
3757
+ }
3758
+ /**
3759
+ * Get workflow instance from IndexedDB.
3760
+ */
3761
+ async getInstance(executionId) {
3762
+ return await this.db.instances.get(executionId) || null;
3763
+ }
3764
+ /**
3765
+ * Update workflow instance in IndexedDB.
3766
+ */
3767
+ async updateInstance(instance) {
3768
+ instance.updatedAt = new Date().toISOString();
3769
+ await this.db.instances.update(instance.id, instance);
3770
+ }
3502
3771
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCWorkflowExecutionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3503
3772
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCWorkflowExecutionService }); }
3504
3773
  }
@@ -3506,10 +3775,906 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
3506
3775
  type: Injectable
3507
3776
  }] });
3508
3777
 
3778
+ /**
3779
+ * Mock workflow definitions for testing and demonstration.
3780
+ */
3781
+ const workflowDefinitionMock = [
3782
+ // Create User Workflow
3783
+ {
3784
+ $schema: 'https://elsaworkflows.io/schemas/workflow-definition/v3.0.0/schema.json',
3785
+ id: AXPDataGenerator.uuid(),
3786
+ definitionId: 'create-user-workflow',
3787
+ tenantId: null,
3788
+ name: 'Create User Workflow',
3789
+ description: 'Complete user registration workflow with permission check, form display, validation, and database save',
3790
+ createdAt: new Date().toISOString(),
3791
+ version: 1,
3792
+ toolVersion: '3.2.0.0',
3793
+ variables: [],
3794
+ inputs: [
3795
+ {
3796
+ type: 'String',
3797
+ name: 'currentUserId',
3798
+ displayName: 'Current User ID',
3799
+ description: 'ID of the user initiating the workflow',
3800
+ },
3801
+ ],
3802
+ outputs: [
3803
+ {
3804
+ type: 'Object',
3805
+ name: 'createdUser',
3806
+ displayName: 'Created User',
3807
+ description: 'The newly created user object',
3808
+ },
3809
+ ],
3810
+ outcomes: ['Done', 'NoPermission', 'Cancelled'],
3811
+ customProperties: {},
3812
+ isReadonly: false,
3813
+ isSystem: false,
3814
+ isLatest: true,
3815
+ isPublished: true,
3816
+ options: {
3817
+ usableAsActivity: false,
3818
+ autoUpdateConsumingWorkflows: false,
3819
+ },
3820
+ root: {
3821
+ id: 'root-flowchart',
3822
+ nodeId: 'root-flowchart',
3823
+ type: 'Elsa.Flowchart',
3824
+ version: 1,
3825
+ activities: [
3826
+ {
3827
+ id: 'check-permission',
3828
+ nodeId: 'check-permission',
3829
+ name: 'Check User Create Permission',
3830
+ type: 'Elsa.CheckPermission',
3831
+ version: 1,
3832
+ executionMode: 'backend',
3833
+ permission: {
3834
+ typeName: 'String',
3835
+ expression: {
3836
+ type: 'Literal',
3837
+ value: 'Users.Create',
3838
+ },
3839
+ },
3840
+ metadata: {
3841
+ designer: {
3842
+ position: {
3843
+ x: 100,
3844
+ y: 100,
3845
+ },
3846
+ },
3847
+ },
3848
+ },
3849
+ {
3850
+ id: 'show-error-toast',
3851
+ nodeId: 'show-error-toast',
3852
+ name: 'Show Permission Error',
3853
+ type: 'Elsa.ShowToast',
3854
+ version: 1,
3855
+ executionMode: 'frontend',
3856
+ message: {
3857
+ typeName: 'String',
3858
+ expression: {
3859
+ type: 'Literal',
3860
+ value: "You don't have permission to create users",
3861
+ },
3862
+ },
3863
+ type_: {
3864
+ typeName: 'String',
3865
+ expression: {
3866
+ type: 'Literal',
3867
+ value: 'error',
3868
+ },
3869
+ },
3870
+ metadata: {
3871
+ designer: {
3872
+ position: {
3873
+ x: 100,
3874
+ y: 250,
3875
+ },
3876
+ },
3877
+ },
3878
+ },
3879
+ {
3880
+ id: 'show-user-form',
3881
+ nodeId: 'show-user-form',
3882
+ name: 'Show User Registration Form',
3883
+ type: 'Elsa.ShowDialog',
3884
+ version: 1,
3885
+ executionMode: 'frontend',
3886
+ formDefinition: {
3887
+ typeName: 'String',
3888
+ expression: {
3889
+ type: 'Literal',
3890
+ value: 'user-create-form',
3891
+ },
3892
+ },
3893
+ title: {
3894
+ typeName: 'String',
3895
+ expression: {
3896
+ type: 'Literal',
3897
+ value: 'Create New User',
3898
+ },
3899
+ },
3900
+ metadata: {
3901
+ designer: {
3902
+ position: {
3903
+ x: 300,
3904
+ y: 100,
3905
+ },
3906
+ },
3907
+ },
3908
+ },
3909
+ {
3910
+ id: 'validate-email',
3911
+ nodeId: 'validate-email',
3912
+ name: 'Check Email Uniqueness',
3913
+ type: 'Elsa.ExecuteQuery',
3914
+ version: 1,
3915
+ executionMode: 'backend',
3916
+ queryKey: {
3917
+ typeName: 'String',
3918
+ expression: {
3919
+ type: 'Literal',
3920
+ value: 'User:CheckEmailExists',
3921
+ },
3922
+ },
3923
+ parameters: {
3924
+ typeName: 'Object',
3925
+ expression: {
3926
+ type: 'JavaScript',
3927
+ value: "{ email: getVariable('userEmail') }",
3928
+ },
3929
+ },
3930
+ metadata: {
3931
+ designer: {
3932
+ position: {
3933
+ x: 500,
3934
+ y: 100,
3935
+ },
3936
+ },
3937
+ },
3938
+ },
3939
+ {
3940
+ id: 'show-validation-error',
3941
+ nodeId: 'show-validation-error',
3942
+ name: 'Show Email Exists Error',
3943
+ type: 'Elsa.ShowToast',
3944
+ version: 1,
3945
+ executionMode: 'frontend',
3946
+ message: {
3947
+ typeName: 'String',
3948
+ expression: {
3949
+ type: 'Literal',
3950
+ value: 'Email already exists. Please use a different email.',
3951
+ },
3952
+ },
3953
+ type_: {
3954
+ typeName: 'String',
3955
+ expression: {
3956
+ type: 'Literal',
3957
+ value: 'error',
3958
+ },
3959
+ },
3960
+ metadata: {
3961
+ designer: {
3962
+ position: {
3963
+ x: 500,
3964
+ y: 250,
3965
+ },
3966
+ },
3967
+ },
3968
+ },
3969
+ {
3970
+ id: 'save-user',
3971
+ nodeId: 'save-user',
3972
+ name: 'Save User to Database',
3973
+ type: 'Elsa.ExecuteCommand',
3974
+ version: 1,
3975
+ executionMode: 'backend',
3976
+ commandKey: {
3977
+ typeName: 'String',
3978
+ expression: {
3979
+ type: 'Literal',
3980
+ value: 'User:Create',
3981
+ },
3982
+ },
3983
+ input: {
3984
+ typeName: 'Object',
3985
+ expression: {
3986
+ type: 'JavaScript',
3987
+ value: "{ email: getVariable('userEmail'), name: getVariable('userName'), role: getVariable('userRole') }",
3988
+ },
3989
+ },
3990
+ metadata: {
3991
+ designer: {
3992
+ position: {
3993
+ x: 700,
3994
+ y: 100,
3995
+ },
3996
+ },
3997
+ },
3998
+ },
3999
+ {
4000
+ id: 'show-success-toast',
4001
+ nodeId: 'show-success-toast',
4002
+ name: 'Show Success Message',
4003
+ type: 'Elsa.ShowToast',
4004
+ version: 1,
4005
+ executionMode: 'frontend',
4006
+ message: {
4007
+ typeName: 'String',
4008
+ expression: {
4009
+ type: 'Literal',
4010
+ value: 'User created successfully',
4011
+ },
4012
+ },
4013
+ type_: {
4014
+ typeName: 'String',
4015
+ expression: {
4016
+ type: 'Literal',
4017
+ value: 'success',
4018
+ },
4019
+ },
4020
+ metadata: {
4021
+ designer: {
4022
+ position: {
4023
+ x: 900,
4024
+ y: 100,
4025
+ },
4026
+ },
4027
+ },
4028
+ },
4029
+ ],
4030
+ connections: [
4031
+ {
4032
+ source: {
4033
+ activity: 'check-permission',
4034
+ port: 'NoPermission',
4035
+ },
4036
+ target: {
4037
+ activity: 'show-error-toast',
4038
+ },
4039
+ },
4040
+ {
4041
+ source: {
4042
+ activity: 'check-permission',
4043
+ port: 'HasPermission',
4044
+ },
4045
+ target: {
4046
+ activity: 'show-user-form',
4047
+ },
4048
+ },
4049
+ {
4050
+ source: {
4051
+ activity: 'show-user-form',
4052
+ port: 'Submitted',
4053
+ },
4054
+ target: {
4055
+ activity: 'validate-email',
4056
+ },
4057
+ },
4058
+ {
4059
+ source: {
4060
+ activity: 'show-user-form',
4061
+ port: 'Cancelled',
4062
+ },
4063
+ target: {
4064
+ activity: 'show-error-toast',
4065
+ },
4066
+ },
4067
+ {
4068
+ source: {
4069
+ activity: 'validate-email',
4070
+ port: 'Exists',
4071
+ },
4072
+ target: {
4073
+ activity: 'show-validation-error',
4074
+ },
4075
+ },
4076
+ {
4077
+ source: {
4078
+ activity: 'show-validation-error',
4079
+ port: 'Done',
4080
+ },
4081
+ target: {
4082
+ activity: 'show-user-form',
4083
+ },
4084
+ },
4085
+ {
4086
+ source: {
4087
+ activity: 'validate-email',
4088
+ port: 'Valid',
4089
+ },
4090
+ target: {
4091
+ activity: 'save-user',
4092
+ },
4093
+ },
4094
+ {
4095
+ source: {
4096
+ activity: 'save-user',
4097
+ port: 'Done',
4098
+ },
4099
+ target: {
4100
+ activity: 'show-success-toast',
4101
+ },
4102
+ },
4103
+ ],
4104
+ variables: [],
4105
+ },
4106
+ },
4107
+ // Simple Welcome Workflow
4108
+ {
4109
+ $schema: 'https://elsaworkflows.io/schemas/workflow-definition/v3.0.0/schema.json',
4110
+ id: AXPDataGenerator.uuid(),
4111
+ definitionId: 'welcome-workflow',
4112
+ tenantId: null,
4113
+ name: 'Welcome Workflow',
4114
+ description: 'Simple workflow to welcome new users',
4115
+ createdAt: new Date().toISOString(),
4116
+ version: 1,
4117
+ toolVersion: '3.2.0.0',
4118
+ variables: [],
4119
+ inputs: [
4120
+ {
4121
+ type: 'String',
4122
+ name: 'userName',
4123
+ displayName: 'User Name',
4124
+ description: 'Name of the user to welcome',
4125
+ },
4126
+ ],
4127
+ outputs: [],
4128
+ outcomes: ['Done'],
4129
+ customProperties: {},
4130
+ isReadonly: false,
4131
+ isSystem: false,
4132
+ isLatest: true,
4133
+ isPublished: true,
4134
+ options: {
4135
+ usableAsActivity: false,
4136
+ autoUpdateConsumingWorkflows: false,
4137
+ },
4138
+ root: {
4139
+ id: 'root-flowchart',
4140
+ nodeId: 'root-flowchart',
4141
+ type: 'Elsa.Flowchart',
4142
+ version: 1,
4143
+ activities: [
4144
+ {
4145
+ id: 'welcome-toast',
4146
+ nodeId: 'welcome-toast',
4147
+ name: 'Show Welcome Message',
4148
+ type: 'Elsa.ShowToast',
4149
+ version: 1,
4150
+ executionMode: 'frontend',
4151
+ message: {
4152
+ typeName: 'String',
4153
+ expression: {
4154
+ type: 'JavaScript',
4155
+ value: "'Welcome ' + getInput('userName') + '!'",
4156
+ },
4157
+ },
4158
+ type_: {
4159
+ typeName: 'String',
4160
+ expression: {
4161
+ type: 'Literal',
4162
+ value: 'success',
4163
+ },
4164
+ },
4165
+ metadata: {
4166
+ designer: {
4167
+ position: {
4168
+ x: 100,
4169
+ y: 100,
4170
+ },
4171
+ },
4172
+ },
4173
+ },
4174
+ ],
4175
+ connections: [],
4176
+ variables: [],
4177
+ },
4178
+ },
4179
+ // Data Processing Workflow
4180
+ {
4181
+ $schema: 'https://elsaworkflows.io/schemas/workflow-definition/v3.0.0/schema.json',
4182
+ id: AXPDataGenerator.uuid(),
4183
+ definitionId: 'data-processing-workflow',
4184
+ tenantId: null,
4185
+ name: 'Data Processing Workflow',
4186
+ description: 'Backend workflow for data processing and validation',
4187
+ createdAt: new Date().toISOString(),
4188
+ version: 1,
4189
+ toolVersion: '3.2.0.0',
4190
+ variables: [],
4191
+ inputs: [
4192
+ {
4193
+ type: 'Object',
4194
+ name: 'data',
4195
+ displayName: 'Data',
4196
+ description: 'Data to process',
4197
+ },
4198
+ ],
4199
+ outputs: [
4200
+ {
4201
+ type: 'Object',
4202
+ name: 'processedData',
4203
+ displayName: 'Processed Data',
4204
+ description: 'Processed data result',
4205
+ },
4206
+ ],
4207
+ outcomes: ['Done', 'Failed'],
4208
+ customProperties: {},
4209
+ isReadonly: false,
4210
+ isSystem: false,
4211
+ isLatest: true,
4212
+ isPublished: true,
4213
+ options: {
4214
+ usableAsActivity: false,
4215
+ autoUpdateConsumingWorkflows: false,
4216
+ },
4217
+ root: {
4218
+ id: 'root-flowchart',
4219
+ nodeId: 'root-flowchart',
4220
+ type: 'Elsa.Flowchart',
4221
+ version: 1,
4222
+ activities: [
4223
+ {
4224
+ id: 'validate-data',
4225
+ nodeId: 'validate-data',
4226
+ name: 'Validate Data',
4227
+ type: 'Elsa.ExecuteQuery',
4228
+ version: 1,
4229
+ executionMode: 'backend',
4230
+ queryKey: {
4231
+ typeName: 'String',
4232
+ expression: {
4233
+ type: 'Literal',
4234
+ value: 'Data:Validate',
4235
+ },
4236
+ },
4237
+ parameters: {
4238
+ typeName: 'Object',
4239
+ expression: {
4240
+ type: 'JavaScript',
4241
+ value: "{ data: getInput('data') }",
4242
+ },
4243
+ },
4244
+ metadata: {
4245
+ designer: {
4246
+ position: {
4247
+ x: 100,
4248
+ y: 100,
4249
+ },
4250
+ },
4251
+ },
4252
+ },
4253
+ {
4254
+ id: 'process-data',
4255
+ nodeId: 'process-data',
4256
+ name: 'Process Data',
4257
+ type: 'Elsa.ExecuteCommand',
4258
+ version: 1,
4259
+ executionMode: 'backend',
4260
+ commandKey: {
4261
+ typeName: 'String',
4262
+ expression: {
4263
+ type: 'Literal',
4264
+ value: 'Data:Process',
4265
+ },
4266
+ },
4267
+ input: {
4268
+ typeName: 'Object',
4269
+ expression: {
4270
+ type: 'JavaScript',
4271
+ value: "{ data: getInput('data') }",
4272
+ },
4273
+ },
4274
+ metadata: {
4275
+ designer: {
4276
+ position: {
4277
+ x: 300,
4278
+ y: 100,
4279
+ },
4280
+ },
4281
+ },
4282
+ },
4283
+ ],
4284
+ connections: [
4285
+ {
4286
+ source: {
4287
+ activity: 'validate-data',
4288
+ port: 'Valid',
4289
+ },
4290
+ target: {
4291
+ activity: 'process-data',
4292
+ },
4293
+ },
4294
+ ],
4295
+ variables: [],
4296
+ },
4297
+ },
4298
+ ];
4299
+ /**
4300
+ * Export definitionId list for easy access
4301
+ */
4302
+ const workflowDefinitionIds = {
4303
+ createUser: 'create-user-workflow',
4304
+ welcome: 'welcome-workflow',
4305
+ dataProcessing: 'data-processing-workflow',
4306
+ };
4307
+
4308
+ /**
4309
+ * Seeds workflow definitions into localStorage for mock/demo purposes.
4310
+ *
4311
+ * Workflow definitions are stored in localStorage with key pattern:
4312
+ * `workflow:{definitionId}`
4313
+ *
4314
+ * This allows the mock workflow execution service to retrieve definitions
4315
+ * without making HTTP calls.
4316
+ */
4317
+ let AXCWorkflowDefinitionDataSeeder$1 = class AXCWorkflowDefinitionDataSeeder {
4318
+ constructor() {
4319
+ this.storageService = inject(AXPEntityStorageService);
4320
+ }
4321
+ async seed() {
4322
+ // Store each workflow definition in localStorage
4323
+ for (const workflow of workflowDefinitionMock) {
4324
+ localStorage.setItem(`workflow:${workflow.definitionId}`, JSON.stringify(workflow));
4325
+ console.log(`[WorkflowDefinitionSeeder] Seeded workflow: ${workflow.name} (${workflow.definitionId})`);
4326
+ }
4327
+ // Also store in entity storage for entity-based access
4328
+ await this.storageService.initial('Workflow.WorkflowDefinition', workflowDefinitionMock);
4329
+ console.log(`[WorkflowDefinitionSeeder] Successfully seeded ${workflowDefinitionMock.length} workflow definitions`);
4330
+ }
4331
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCWorkflowDefinitionDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4332
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCWorkflowDefinitionDataSeeder }); }
4333
+ };
4334
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCWorkflowDefinitionDataSeeder$1, decorators: [{
4335
+ type: Injectable
4336
+ }] });
4337
+
4338
+ //#endregion
4339
+ /**
4340
+ * CheckPermission Activity (Backend)
4341
+ *
4342
+ * Checks if a user has specific permission.
4343
+ * This is a mock implementation that always grants permission for demo purposes.
4344
+ *
4345
+ * In production, this would check against real permission system.
4346
+ *
4347
+ * Execution Mode: backend
4348
+ * Activity Type: workflow-activity:check-permission
4349
+ *
4350
+ * Outcomes:
4351
+ * - HasPermission: User has the permission
4352
+ * - NoPermission: User does not have the permission
4353
+ */
4354
+ class CheckPermissionActivity {
4355
+ //#region ---- AXPCommand Implementation ----
4356
+ async execute(input) {
4357
+ // Mock implementation: always grant permission for demo
4358
+ // In production, check against permission service
4359
+ const hasPermission = true; // TODO: Integrate with real permission system
4360
+ const output = {
4361
+ hasPermission,
4362
+ userId: input.userId || 'current-user',
4363
+ permission: input.permission,
4364
+ };
4365
+ // Determine outcome based on permission check
4366
+ const outcomes = hasPermission
4367
+ ? { HasPermission: true }
4368
+ : { NoPermission: true };
4369
+ console.log(`[CheckPermissionActivity] Checked permission '${input.permission}' for user '${output.userId}': ${hasPermission ? 'GRANTED' : 'DENIED'}`);
4370
+ return {
4371
+ output,
4372
+ outcomes,
4373
+ };
4374
+ }
4375
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: CheckPermissionActivity, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4376
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: CheckPermissionActivity }); }
4377
+ }
4378
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: CheckPermissionActivity, decorators: [{
4379
+ type: Injectable
4380
+ }] });
4381
+
4382
+ //#endregion
4383
+ /**
4384
+ * ExecuteQuery Activity (Backend)
4385
+ *
4386
+ * Executes a query operation.
4387
+ * This is a mock implementation that simulates common queries.
4388
+ *
4389
+ * Execution Mode: backend
4390
+ * Activity Type: workflow-activity:execute-query
4391
+ *
4392
+ * Outcomes:
4393
+ * - Done: Query executed successfully
4394
+ * - Valid: Data is valid (for validation queries)
4395
+ * - Exists: Data exists (for existence checks)
4396
+ * - NotFound: Data not found
4397
+ * - Failed: Query execution failed
4398
+ */
4399
+ class ExecuteQueryActivity {
4400
+ constructor() {
4401
+ //#region ---- Services ----
4402
+ this.storageService = inject(AXPEntityStorageService);
4403
+ }
4404
+ //#endregion
4405
+ //#region ---- AXPCommand Implementation ----
4406
+ async execute(input) {
4407
+ try {
4408
+ console.log(`[ExecuteQueryActivity] Executing query '${input.queryKey}' with parameters:`, input.parameters);
4409
+ // Route to appropriate query handler based on queryKey
4410
+ const result = await this.routeQuery(input.queryKey, input.parameters || {});
4411
+ return result;
4412
+ }
4413
+ catch (error) {
4414
+ console.error(`[ExecuteQueryActivity] Query '${input.queryKey}' failed:`, error);
4415
+ return {
4416
+ output: {
4417
+ data: null,
4418
+ success: false,
4419
+ error: error.message || 'Unknown error',
4420
+ },
4421
+ outcomes: {
4422
+ Failed: true,
4423
+ },
4424
+ };
4425
+ }
4426
+ }
4427
+ //#endregion
4428
+ //#region ---- Query Routing ----
4429
+ /**
4430
+ * Routes query to appropriate handler based on queryKey.
4431
+ */
4432
+ async routeQuery(queryKey, parameters) {
4433
+ switch (queryKey) {
4434
+ case 'User:CheckEmailExists':
4435
+ return await this.checkEmailExists(parameters);
4436
+ case 'Data:Validate':
4437
+ return await this.validateData(parameters);
4438
+ default:
4439
+ // Mock: return empty result for unknown queries
4440
+ console.warn(`[ExecuteQueryActivity] Unknown query key: ${queryKey}`);
4441
+ return {
4442
+ output: {
4443
+ data: null,
4444
+ success: true,
4445
+ },
4446
+ outcomes: {
4447
+ Done: true,
4448
+ },
4449
+ };
4450
+ }
4451
+ }
4452
+ //#endregion
4453
+ //#region ---- Query Handlers ----
4454
+ /**
4455
+ * Checks if email already exists in database.
4456
+ */
4457
+ async checkEmailExists(parameters) {
4458
+ const email = parameters['email'] || parameters['userEmail'];
4459
+ // Mock implementation: randomly decide if email exists
4460
+ // In production, check against real database
4461
+ const exists = Math.random() > 0.8; // 20% chance email exists
4462
+ console.log(`[ExecuteQueryActivity] Checking email '${email}': ${exists ? 'EXISTS' : 'AVAILABLE'}`);
4463
+ const outcome = exists ? 'Exists' : 'Valid';
4464
+ return {
4465
+ output: {
4466
+ data: {
4467
+ email,
4468
+ exists,
4469
+ available: !exists,
4470
+ },
4471
+ success: true,
4472
+ },
4473
+ outcomes: {
4474
+ [outcome]: true,
4475
+ Done: true,
4476
+ },
4477
+ };
4478
+ }
4479
+ /**
4480
+ * Validates data structure and content.
4481
+ */
4482
+ async validateData(parameters) {
4483
+ const data = parameters['data'];
4484
+ // Mock validation: check if data exists and has content
4485
+ const isValid = data && Object.keys(data).length > 0;
4486
+ console.log(`[ExecuteQueryActivity] Validating data: ${isValid ? 'VALID' : 'INVALID'}`);
4487
+ const outcome = isValid ? 'Valid' : 'Invalid';
4488
+ return {
4489
+ output: {
4490
+ data: {
4491
+ valid: isValid,
4492
+ errors: isValid ? [] : ['Data is empty or invalid'],
4493
+ },
4494
+ success: true,
4495
+ },
4496
+ outcomes: {
4497
+ [outcome]: true,
4498
+ Done: true,
4499
+ },
4500
+ };
4501
+ }
4502
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: ExecuteQueryActivity, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4503
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: ExecuteQueryActivity }); }
4504
+ }
4505
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: ExecuteQueryActivity, decorators: [{
4506
+ type: Injectable
4507
+ }] });
4508
+
4509
+ //#endregion
4510
+ /**
4511
+ * ExecuteCommand Activity (Backend)
4512
+ *
4513
+ * Executes a command operation.
4514
+ * This is a mock implementation that simulates common commands.
4515
+ *
4516
+ * Execution Mode: backend
4517
+ * Activity Type: workflow-activity:execute-command
4518
+ *
4519
+ * Outcomes:
4520
+ * - Done: Command executed successfully
4521
+ * - Failed: Command execution failed
4522
+ */
4523
+ class ExecuteCommandActivity {
4524
+ constructor() {
4525
+ //#region ---- Services ----
4526
+ this.storageService = inject(AXPEntityStorageService);
4527
+ }
4528
+ //#endregion
4529
+ //#region ---- AXPCommand Implementation ----
4530
+ async execute(input) {
4531
+ try {
4532
+ console.log(`[ExecuteCommandActivity] Executing command '${input.commandKey}' with input:`, input.input);
4533
+ // Route to appropriate command handler based on commandKey
4534
+ const result = await this.routeCommand(input.commandKey, input.input || {});
4535
+ return result;
4536
+ }
4537
+ catch (error) {
4538
+ console.error(`[ExecuteCommandActivity] Command '${input.commandKey}' failed:`, error);
4539
+ return {
4540
+ output: {
4541
+ result: null,
4542
+ success: false,
4543
+ error: error.message || 'Unknown error',
4544
+ },
4545
+ outcomes: {
4546
+ Failed: true,
4547
+ },
4548
+ };
4549
+ }
4550
+ }
4551
+ //#endregion
4552
+ //#region ---- Command Routing ----
4553
+ /**
4554
+ * Routes command to appropriate handler based on commandKey.
4555
+ */
4556
+ async routeCommand(commandKey, input) {
4557
+ switch (commandKey) {
4558
+ case 'User:Create':
4559
+ return await this.createUser(input);
4560
+ case 'Data:Process':
4561
+ return await this.processData(input);
4562
+ default:
4563
+ // Mock: return success for unknown commands
4564
+ console.warn(`[ExecuteCommandActivity] Unknown command key: ${commandKey}`);
4565
+ return {
4566
+ output: {
4567
+ result: { success: true },
4568
+ success: true,
4569
+ },
4570
+ outcomes: {
4571
+ Done: true,
4572
+ },
4573
+ };
4574
+ }
4575
+ }
4576
+ //#endregion
4577
+ //#region ---- Command Handlers ----
4578
+ /**
4579
+ * Creates a new user in the system.
4580
+ */
4581
+ async createUser(input) {
4582
+ // Extract user data from input
4583
+ const email = input['email'] || input['userEmail'];
4584
+ const name = input['name'] || input['userName'] || 'New User';
4585
+ const role = input['role'] || input['userRole'] || 'User';
4586
+ // Create new user object
4587
+ const userId = AXPDataGenerator.uuid();
4588
+ const newUser = {
4589
+ id: userId,
4590
+ email,
4591
+ name,
4592
+ role,
4593
+ createdAt: new Date().toISOString(),
4594
+ isActive: true,
4595
+ };
4596
+ console.log(`[ExecuteCommandActivity] Creating user:`, newUser);
4597
+ // In production, save to database via EntityStorageService or API
4598
+ // For mock, we'll just simulate success
4599
+ // await this.storageService.create('User', newUser);
4600
+ return {
4601
+ output: {
4602
+ result: newUser,
4603
+ success: true,
4604
+ entityId: userId,
4605
+ },
4606
+ outcomes: {
4607
+ Done: true,
4608
+ },
4609
+ };
4610
+ }
4611
+ /**
4612
+ * Processes data according to business rules.
4613
+ */
4614
+ async processData(input) {
4615
+ const data = input['data'];
4616
+ // Mock processing: just add timestamp and processed flag
4617
+ const processedData = {
4618
+ ...data,
4619
+ processed: true,
4620
+ processedAt: new Date().toISOString(),
4621
+ };
4622
+ console.log(`[ExecuteCommandActivity] Processed data:`, processedData);
4623
+ return {
4624
+ output: {
4625
+ result: processedData,
4626
+ success: true,
4627
+ },
4628
+ outcomes: {
4629
+ Done: true,
4630
+ },
4631
+ };
4632
+ }
4633
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: ExecuteCommandActivity, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4634
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: ExecuteCommandActivity }); }
4635
+ }
4636
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: ExecuteCommandActivity, decorators: [{
4637
+ type: Injectable
4638
+ }] });
4639
+
4640
+ /**
4641
+ * Provides all backend workflow activities as Commands.
4642
+ *
4643
+ * These activities are registered with the CommandBus and can be executed
4644
+ * by the workflow execution service.
4645
+ *
4646
+ * Usage:
4647
+ * ```typescript
4648
+ * @NgModule({
4649
+ * providers: [
4650
+ * provideWorkflowActivities(),
4651
+ * ]
4652
+ * })
4653
+ * export class AppModule {}
4654
+ * ```
4655
+ */
4656
+ function provideWorkflowActivities() {
4657
+ return provideCommandSetups([
4658
+ {
4659
+ key: 'workflow-activity:check-permission',
4660
+ command: () => CheckPermissionActivity,
4661
+ },
4662
+ {
4663
+ key: 'workflow-activity:execute-query',
4664
+ command: () => ExecuteQueryActivity,
4665
+ },
4666
+ {
4667
+ key: 'workflow-activity:execute-command',
4668
+ command: () => ExecuteCommandActivity,
4669
+ },
4670
+ ]);
4671
+ }
4672
+
3509
4673
  class AXCCommonMockModule {
3510
4674
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCommonMockModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
3511
4675
  static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.10", ngImport: i0, type: AXCCommonMockModule }); }
3512
4676
  static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCommonMockModule, providers: [
4677
+ provideWorkflowActivities(),
3513
4678
  {
3514
4679
  provide: AXP_ACTIVITY_LOG_PROVIDER,
3515
4680
  useClass: AXCPActivityLogService,
@@ -3530,7 +4695,7 @@ class AXCCommonMockModule {
3530
4695
  },
3531
4696
  {
3532
4697
  provide: AXPVersioningService,
3533
- useClass: VersioningService,
4698
+ useClass: AXCVersioningService,
3534
4699
  },
3535
4700
  {
3536
4701
  provide: AXP_ACTIVITY_CATEGORY_PROVIDER,
@@ -3546,6 +4711,11 @@ class AXCCommonMockModule {
3546
4711
  provide: AXPWorkflowExecutionService,
3547
4712
  useClass: AXCWorkflowExecutionService,
3548
4713
  },
4714
+ {
4715
+ provide: AXP_DATA_SEEDER_TOKEN,
4716
+ useClass: AXCWorkflowDefinitionDataSeeder$1,
4717
+ multi: true,
4718
+ },
3549
4719
  ] }); }
3550
4720
  }
3551
4721
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCommonMockModule, decorators: [{
@@ -3555,6 +4725,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
3555
4725
  exports: [],
3556
4726
  declarations: [],
3557
4727
  providers: [
4728
+ provideWorkflowActivities(),
3558
4729
  {
3559
4730
  provide: AXP_ACTIVITY_LOG_PROVIDER,
3560
4731
  useClass: AXCPActivityLogService,
@@ -3575,7 +4746,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
3575
4746
  },
3576
4747
  {
3577
4748
  provide: AXPVersioningService,
3578
- useClass: VersioningService,
4749
+ useClass: AXCVersioningService,
3579
4750
  },
3580
4751
  {
3581
4752
  provide: AXP_ACTIVITY_CATEGORY_PROVIDER,
@@ -3591,6 +4762,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
3591
4762
  provide: AXPWorkflowExecutionService,
3592
4763
  useClass: AXCWorkflowExecutionService,
3593
4764
  },
4765
+ {
4766
+ provide: AXP_DATA_SEEDER_TOKEN,
4767
+ useClass: AXCWorkflowDefinitionDataSeeder$1,
4768
+ multi: true,
4769
+ },
3594
4770
  ],
3595
4771
  }]
3596
4772
  }] });
@@ -37463,6 +38639,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
37463
38639
  }]
37464
38640
  }] });
37465
38641
 
38642
+ /**
38643
+ * Mock workflow definition entities for the entity list.
38644
+ */
38645
+ const workflowDefinitionEntityMock = workflowDefinitionMock.map((def) => ({
38646
+ id: def.id,
38647
+ definitionId: def.definitionId,
38648
+ name: def.name || 'Unnamed Workflow',
38649
+ description: def.description || undefined,
38650
+ version: def.version,
38651
+ isLatest: def.isLatest,
38652
+ isPublished: def.isPublished,
38653
+ isReadonly: def.isReadonly,
38654
+ isSystem: def.isSystem,
38655
+ createdAt: def.createdAt,
38656
+ workflowDefinition: def,
38657
+ }));
38658
+
38659
+ class AXCWorkflowDefinitionDataSeeder {
38660
+ constructor() {
38661
+ this.storageService = inject(AXPEntityStorageService);
38662
+ }
38663
+ async seed() {
38664
+ await this.storageService.initial(`${RootConfig$m.module.name}.${RootConfig$m.entities.workflowDefinition.name}`, workflowDefinitionEntityMock);
38665
+ console.log(`[WorkflowDefinitionSeeder] Seeded ${workflowDefinitionEntityMock.length} workflow definitions`);
38666
+ }
38667
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCWorkflowDefinitionDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
38668
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCWorkflowDefinitionDataSeeder }); }
38669
+ }
38670
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCWorkflowDefinitionDataSeeder, decorators: [{
38671
+ type: Injectable
38672
+ }] });
38673
+
37466
38674
  class AXCWorkflowManagementMockModule {
37467
38675
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCWorkflowManagementMockModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
37468
38676
  static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.10", ngImport: i0, type: AXCWorkflowManagementMockModule }); }
@@ -37473,16 +38681,11 @@ class AXCWorkflowManagementMockModule {
37473
38681
  command: () => import('./acorex-connectivity-mock-distribution-record.command-w3zoeELy.mjs').then((c) => c.AXCDistributionCommand),
37474
38682
  },
37475
38683
  ]),
37476
- // {
37477
- // provide: AXP_WORKFLOW_TASK_PROVIDER,
37478
- // useClass: AXPTaskBoardProjectManagementTaskProvider,
37479
- // multi: true,
37480
- // },
37481
- // {
37482
- // provide: AXP_WORKFLOW_TASK_PROVIDER,
37483
- // useClass: AXPTaskBoardPlatformManagementTaskProvider,
37484
- // multi: true,
37485
- // },
38684
+ {
38685
+ provide: AXP_DATA_SEEDER_TOKEN,
38686
+ useClass: AXCWorkflowDefinitionDataSeeder,
38687
+ multi: true,
38688
+ },
37486
38689
  ] }); }
37487
38690
  }
37488
38691
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCWorkflowManagementMockModule, decorators: [{
@@ -37498,16 +38701,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
37498
38701
  command: () => import('./acorex-connectivity-mock-distribution-record.command-w3zoeELy.mjs').then((c) => c.AXCDistributionCommand),
37499
38702
  },
37500
38703
  ]),
37501
- // {
37502
- // provide: AXP_WORKFLOW_TASK_PROVIDER,
37503
- // useClass: AXPTaskBoardProjectManagementTaskProvider,
37504
- // multi: true,
37505
- // },
37506
- // {
37507
- // provide: AXP_WORKFLOW_TASK_PROVIDER,
37508
- // useClass: AXPTaskBoardPlatformManagementTaskProvider,
37509
- // multi: true,
37510
- // },
38704
+ {
38705
+ provide: AXP_DATA_SEEDER_TOKEN,
38706
+ useClass: AXCWorkflowDefinitionDataSeeder,
38707
+ multi: true,
38708
+ },
37511
38709
  ],
37512
38710
  }]
37513
38711
  }] });
@@ -38870,7 +40068,7 @@ class AXCApplicationDataSeeder {
38870
40068
  this.storageService = inject(AXPEntityStorageService);
38871
40069
  }
38872
40070
  async seed() {
38873
- await this.storageService.initial(`${RootConfig$m.module.name}.${RootConfig$m.entities.application.name}`, APPLICATIONS);
40071
+ await this.storageService.initial(`${RootConfig$n.module.name}.${RootConfig$n.entities.application.name}`, APPLICATIONS);
38874
40072
  }
38875
40073
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCApplicationDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
38876
40074
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCApplicationDataSeeder }); }
@@ -38884,7 +40082,7 @@ class AXCEditionDataSeeder {
38884
40082
  this.storageService = inject(AXPEntityStorageService);
38885
40083
  }
38886
40084
  async seed() {
38887
- await this.storageService.initial(`${RootConfig$m.module.name}.${RootConfig$m.entities.edition.name}`, EDITIONS);
40085
+ await this.storageService.initial(`${RootConfig$n.module.name}.${RootConfig$n.entities.edition.name}`, EDITIONS);
38888
40086
  }
38889
40087
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCEditionDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
38890
40088
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCEditionDataSeeder }); }
@@ -38898,7 +40096,7 @@ class AXCFeatureDataSeeder {
38898
40096
  this.storageService = inject(AXPEntityStorageService);
38899
40097
  }
38900
40098
  async seed() {
38901
- await this.storageService.initial(`${RootConfig$m.module.name}.${RootConfig$m.entities.feature.name}`, FEATURES);
40099
+ await this.storageService.initial(`${RootConfig$n.module.name}.${RootConfig$n.entities.feature.name}`, FEATURES);
38902
40100
  }
38903
40101
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCFeatureDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
38904
40102
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCFeatureDataSeeder }); }
@@ -38912,7 +40110,7 @@ class AXCModuleDataSeeder {
38912
40110
  this.storageService = inject(AXPEntityStorageService);
38913
40111
  }
38914
40112
  async seed() {
38915
- await this.storageService.initial(`${RootConfig$m.module.name}.${RootConfig$m.entities.module.name}`, MODULES);
40113
+ await this.storageService.initial(`${RootConfig$n.module.name}.${RootConfig$n.entities.module.name}`, MODULES);
38916
40114
  }
38917
40115
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCModuleDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
38918
40116
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCModuleDataSeeder }); }
@@ -39195,7 +40393,7 @@ class AXMQuestionBankItemCategoryDataSeeder {
39195
40393
  this.storage = inject(AXPEntityStorageService);
39196
40394
  }
39197
40395
  async seed() {
39198
- await this.storage.initial(`${RootConfig$n.module.name}.${RootConfig$n.entities.questionBankItem.name}Category`, QUESTION_BANK_ITEM_CATEGORY_MOCK);
40396
+ await this.storage.initial(`${RootConfig$o.module.name}.${RootConfig$o.entities.questionBankItem.name}Category`, QUESTION_BANK_ITEM_CATEGORY_MOCK);
39199
40397
  }
39200
40398
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMQuestionBankItemCategoryDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
39201
40399
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMQuestionBankItemCategoryDataSeeder }); }
@@ -39516,7 +40714,7 @@ class AXMQuestionnaireCategoryDataSeeder {
39516
40714
  this.storage = inject(AXPEntityStorageService);
39517
40715
  }
39518
40716
  async seed() {
39519
- await this.storage.initial(`${RootConfig$n.module.name}.${RootConfig$n.entities.questionnaire.name}Category`, QUESTIONNAIRE_CATEGORY_MOCK);
40717
+ await this.storage.initial(`${RootConfig$o.module.name}.${RootConfig$o.entities.questionnaire.name}Category`, QUESTIONNAIRE_CATEGORY_MOCK);
39520
40718
  }
39521
40719
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMQuestionnaireCategoryDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
39522
40720
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMQuestionnaireCategoryDataSeeder }); }
@@ -39530,7 +40728,7 @@ class AXMQuestionBankItemDataSeeder {
39530
40728
  this.storage = inject(AXPEntityStorageService);
39531
40729
  }
39532
40730
  async seed() {
39533
- await this.storage.initial(`${RootConfig$n.module.name}.${RootConfig$n.entities.questionBankItem.name}`, questionBankItemMock);
40731
+ await this.storage.initial(`${RootConfig$o.module.name}.${RootConfig$o.entities.questionBankItem.name}`, questionBankItemMock);
39534
40732
  }
39535
40733
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMQuestionBankItemDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
39536
40734
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMQuestionBankItemDataSeeder }); }
@@ -39544,7 +40742,7 @@ class AXMQuestionnaireDataSeeder {
39544
40742
  this.storage = inject(AXPEntityStorageService);
39545
40743
  }
39546
40744
  async seed() {
39547
- await this.storage.initial(`${RootConfig$n.module.name}.${RootConfig$n.entities.questionnaire.name}`, questionnaireMock);
40745
+ await this.storage.initial(`${RootConfig$o.module.name}.${RootConfig$o.entities.questionnaire.name}`, questionnaireMock);
39548
40746
  }
39549
40747
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMQuestionnaireDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
39550
40748
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMQuestionnaireDataSeeder }); }
@@ -39631,7 +40829,7 @@ class AXMPublicationDataSeeder {
39631
40829
  this.storage = inject(AXPEntityStorageService);
39632
40830
  }
39633
40831
  async seed() {
39634
- await this.storage.initial(`${RootConfig$n.module.name}.${RootConfig$n.entities.publication.name}`, publicationMock);
40832
+ await this.storage.initial(`${RootConfig$o.module.name}.${RootConfig$o.entities.publication.name}`, publicationMock);
39635
40833
  }
39636
40834
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMPublicationDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
39637
40835
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMPublicationDataSeeder }); }
@@ -39732,7 +40930,7 @@ class AXMResponseSessionDataSeeder {
39732
40930
  this.storage = inject(AXPEntityStorageService);
39733
40931
  }
39734
40932
  async seed() {
39735
- await this.storage.initial(`${RootConfig$n.module.name}.${RootConfig$n.entities.responseSession.name}`, responseSessionMock);
40933
+ await this.storage.initial(`${RootConfig$o.module.name}.${RootConfig$o.entities.responseSession.name}`, responseSessionMock);
39736
40934
  }
39737
40935
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMResponseSessionDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
39738
40936
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMResponseSessionDataSeeder }); }
@@ -39818,7 +41016,7 @@ class AXMCollaboratorDataSeeder {
39818
41016
  this.storage = inject(AXPEntityStorageService);
39819
41017
  }
39820
41018
  async seed() {
39821
- await this.storage.initial(`${RootConfig$n.module.name}.${RootConfig$n.entities.collaborator.name}`, collaboratorMock);
41019
+ await this.storage.initial(`${RootConfig$o.module.name}.${RootConfig$o.entities.collaborator.name}`, collaboratorMock);
39822
41020
  }
39823
41021
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMCollaboratorDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
39824
41022
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMCollaboratorDataSeeder }); }
@@ -39927,7 +41125,7 @@ class AXMResponseEntryDataSeeder {
39927
41125
  this.storage = inject(AXPEntityStorageService);
39928
41126
  }
39929
41127
  async seed() {
39930
- await this.storage.initial(`${RootConfig$n.module.name}.${RootConfig$n.entities.responseEntry.name}`, responseEntryMock);
41128
+ await this.storage.initial(`${RootConfig$o.module.name}.${RootConfig$o.entities.responseEntry.name}`, responseEntryMock);
39931
41129
  }
39932
41130
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMResponseEntryDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
39933
41131
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXMResponseEntryDataSeeder }); }
@@ -40055,7 +41253,7 @@ class AXCCustomerTypeDataSeeder {
40055
41253
  this.storageService = inject(AXPEntityStorageService);
40056
41254
  }
40057
41255
  async seed() {
40058
- await this.storageService.initial(RootConfig$o.entities.customerType.source, CUSTOMER_TYPES_MOCK);
41256
+ await this.storageService.initial(RootConfig$p.entities.customerType.source, CUSTOMER_TYPES_MOCK);
40059
41257
  }
40060
41258
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCustomerTypeDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
40061
41259
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCustomerTypeDataSeeder }); }
@@ -40069,7 +41267,7 @@ class AXCCustomerSegmentDataSeeder {
40069
41267
  this.storageService = inject(AXPEntityStorageService);
40070
41268
  }
40071
41269
  async seed() {
40072
- await this.storageService.initial(RootConfig$o.entities.customerSegment.source, CUSTOMER_SEGMENTS_MOCK);
41270
+ await this.storageService.initial(RootConfig$p.entities.customerSegment.source, CUSTOMER_SEGMENTS_MOCK);
40073
41271
  }
40074
41272
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCustomerSegmentDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
40075
41273
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCustomerSegmentDataSeeder }); }
@@ -40083,7 +41281,7 @@ class AXCCustomerDataSeeder {
40083
41281
  this.storageService = inject(AXPEntityStorageService);
40084
41282
  }
40085
41283
  async seed() {
40086
- await this.storageService.initial(RootConfig$o.entities.customer.source, CUSTOMERS_MOCK);
41284
+ await this.storageService.initial(RootConfig$p.entities.customer.source, CUSTOMERS_MOCK);
40087
41285
  }
40088
41286
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCustomerDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
40089
41287
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCustomerDataSeeder }); }
@@ -40107,7 +41305,7 @@ class AXCCrmOpportunityStageDataSeeder {
40107
41305
  this.storageService = inject(AXPEntityStorageService);
40108
41306
  }
40109
41307
  async seed() {
40110
- await this.storageService.initial(RootConfig$o.entities.opportunityStage.source, OPPORTUNITY_STAGES_MOCK);
41308
+ await this.storageService.initial(RootConfig$p.entities.opportunityStage.source, OPPORTUNITY_STAGES_MOCK);
40111
41309
  }
40112
41310
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmOpportunityStageDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
40113
41311
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmOpportunityStageDataSeeder }); }
@@ -40126,7 +41324,7 @@ class AXCCrmSalesPipelineDataSeeder {
40126
41324
  this.storageService = inject(AXPEntityStorageService);
40127
41325
  }
40128
41326
  async seed() {
40129
- await this.storageService.initial(RootConfig$o.entities.salesPipeline.source, SALES_PIPELINES_MOCK);
41327
+ await this.storageService.initial(RootConfig$p.entities.salesPipeline.source, SALES_PIPELINES_MOCK);
40130
41328
  }
40131
41329
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmSalesPipelineDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
40132
41330
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmSalesPipelineDataSeeder }); }
@@ -40149,7 +41347,7 @@ class AXCCrmLifecycleStageDataSeeder {
40149
41347
  this.storageService = inject(AXPEntityStorageService);
40150
41348
  }
40151
41349
  async seed() {
40152
- await this.storageService.initial(RootConfig$o.entities.lifecycleStage.source, LIFECYCLE_STAGES_MOCK);
41350
+ await this.storageService.initial(RootConfig$p.entities.lifecycleStage.source, LIFECYCLE_STAGES_MOCK);
40153
41351
  }
40154
41352
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmLifecycleStageDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
40155
41353
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmLifecycleStageDataSeeder }); }
@@ -40170,7 +41368,7 @@ class AXCCrmSalesTerritoryDataSeeder {
40170
41368
  this.storageService = inject(AXPEntityStorageService);
40171
41369
  }
40172
41370
  async seed() {
40173
- await this.storageService.initial(RootConfig$o.entities.salesTerritory.source, SALES_TERRITORIES_MOCK);
41371
+ await this.storageService.initial(RootConfig$p.entities.salesTerritory.source, SALES_TERRITORIES_MOCK);
40174
41372
  }
40175
41373
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmSalesTerritoryDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
40176
41374
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmSalesTerritoryDataSeeder }); }
@@ -40190,7 +41388,7 @@ class AXCCrmLeadDataSeeder {
40190
41388
  this.storageService = inject(AXPEntityStorageService);
40191
41389
  }
40192
41390
  async seed() {
40193
- await this.storageService.initial(RootConfig$o.entities.lead.source, LEADS_MOCK);
41391
+ await this.storageService.initial(RootConfig$p.entities.lead.source, LEADS_MOCK);
40194
41392
  }
40195
41393
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmLeadDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
40196
41394
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmLeadDataSeeder }); }
@@ -40236,7 +41434,7 @@ class AXCCrmOpportunityDataSeeder {
40236
41434
  this.storageService = inject(AXPEntityStorageService);
40237
41435
  }
40238
41436
  async seed() {
40239
- await this.storageService.initial(RootConfig$o.entities.opportunity.source, OPPORTUNITIES_MOCK);
41437
+ await this.storageService.initial(RootConfig$p.entities.opportunity.source, OPPORTUNITIES_MOCK);
40240
41438
  }
40241
41439
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmOpportunityDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
40242
41440
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmOpportunityDataSeeder }); }
@@ -40256,7 +41454,7 @@ class AXCCrmActivityDataSeeder {
40256
41454
  this.storageService = inject(AXPEntityStorageService);
40257
41455
  }
40258
41456
  async seed() {
40259
- await this.storageService.initial(RootConfig$o.entities.activity.source, ACTIVITIES_MOCK);
41457
+ await this.storageService.initial(RootConfig$p.entities.activity.source, ACTIVITIES_MOCK);
40260
41458
  }
40261
41459
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmActivityDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
40262
41460
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmActivityDataSeeder }); }
@@ -40280,7 +41478,7 @@ class AXCCrmDealContactRoleDataSeeder {
40280
41478
  this.storageService = inject(AXPEntityStorageService);
40281
41479
  }
40282
41480
  async seed() {
40283
- await this.storageService.initial(RootConfig$o.entities.dealContactRole.source, DEAL_CONTACT_ROLES_MOCK);
41481
+ await this.storageService.initial(RootConfig$p.entities.dealContactRole.source, DEAL_CONTACT_ROLES_MOCK);
40284
41482
  }
40285
41483
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmDealContactRoleDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
40286
41484
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCCrmDealContactRoleDataSeeder }); }
@@ -40396,7 +41594,7 @@ class AXPIssueTypeDataSeeder {
40396
41594
  this.storageService = inject(AXPEntityStorageService);
40397
41595
  }
40398
41596
  async seed() {
40399
- await this.storageService.initial(`${RootConfig$p.module.name}.${RootConfig$p.entities.issueType.name}`, ISSUE_TYPES);
41597
+ await this.storageService.initial(`${RootConfig$q.module.name}.${RootConfig$q.entities.issueType.name}`, ISSUE_TYPES);
40400
41598
  }
40401
41599
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXPIssueTypeDataSeeder, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
40402
41600
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXPIssueTypeDataSeeder }); }
@@ -40827,7 +42025,7 @@ const createFileCastMiddleware = {
40827
42025
  const hasValidSource = obj.source &&
40828
42026
  typeof obj.source === 'object' &&
40829
42027
  obj.source.kind &&
40830
- ['blob', 'url', 'preview', 'none', 'fileId'].includes(obj.source.kind);
42028
+ ['blob', 'url', 'preview', 'none', 'fileId', 'reference'].includes(obj.source.kind);
40831
42029
  // At least one of these conditions must be true for it to be a file
40832
42030
  const isFileObject = hasValidStatus || hasValidSource;
40833
42031
  // Additional validation for file-specific properties
@@ -40910,7 +42108,38 @@ const createFileCastMiddleware = {
40910
42108
  // Return null to indicate this file should be removed from the list
40911
42109
  return null;
40912
42110
  }
40913
- // Case 2: Already uploaded file (keep existing ID)
42111
+ // Case 2: Reference-based file (handle document updates)
42112
+ if (file.source?.kind === 'reference' && file.source.value && typeof file.source.value === 'object' && 'id' in file.source.value && 'type' in file.source.value) {
42113
+ const reference = file.source.value;
42114
+ // Only handle document references
42115
+ if (reference.type === 'document' && documentService) {
42116
+ try {
42117
+ const document = await documentService.getOne(reference.id);
42118
+ if (document) {
42119
+ // Check if name has changed and update document if needed
42120
+ if (document.name !== file.name || document.title !== file.name) {
42121
+ try {
42122
+ await documentService.updateOne(reference.id, {
42123
+ name: file.name,
42124
+ title: file.name,
42125
+ });
42126
+ }
42127
+ catch (error) {
42128
+ console.error('[file-cast] Failed to update document name:', error);
42129
+ }
42130
+ }
42131
+ // Return reference identifier
42132
+ return { id: serializeReference(reference), kind: 'reference' };
42133
+ }
42134
+ }
42135
+ catch (error) {
42136
+ console.error('[file-cast] Failed to process reference:', error);
42137
+ }
42138
+ }
42139
+ // For non-document references or if document service is not available, return reference as-is
42140
+ return { id: serializeReference(reference), kind: 'reference' };
42141
+ }
42142
+ // Case 3: Already uploaded file (keep existing ID)
40914
42143
  if ((file.status === 'uploaded' || file.status === 'remote') &&
40915
42144
  file.source?.kind === 'fileId' &&
40916
42145
  typeof file.source.value === 'string') {
@@ -40936,7 +42165,7 @@ const createFileCastMiddleware = {
40936
42165
  }
40937
42166
  return { id: cleanFileId, kind: 'file' };
40938
42167
  }
40939
- // Case 3: New file that needs uploading
42168
+ // Case 4: New file that needs uploading
40940
42169
  if (!file.source?.value) {
40941
42170
  return null;
40942
42171
  }
@@ -40991,25 +42220,45 @@ const createFileCastMiddleware = {
40991
42220
  };
40992
42221
  const FILE_PREFIX = 'file:';
40993
42222
  const DOCUMENT_PREFIX = 'document:';
42223
+ const REFERENCE_PREFIX = 'reference:';
40994
42224
  const addFilePrefix = (fileId) => {
40995
42225
  return `${FILE_PREFIX}${fileId}`;
40996
42226
  };
40997
42227
  const addDocumentPrefix = (docId) => {
40998
42228
  return `${DOCUMENT_PREFIX}${docId}`;
40999
42229
  };
42230
+ const addReferencePrefix = (reference) => {
42231
+ return `${REFERENCE_PREFIX}${reference.type}:${reference.id}`;
42232
+ };
41000
42233
  const removeFilePrefix = (prefixedId) => {
41001
42234
  return prefixedId.startsWith(FILE_PREFIX) ? prefixedId.substring(FILE_PREFIX.length) : prefixedId;
41002
42235
  };
41003
42236
  const removeDocumentPrefix = (prefixedId) => {
41004
42237
  return prefixedId.startsWith(DOCUMENT_PREFIX) ? prefixedId.substring(DOCUMENT_PREFIX.length) : prefixedId;
41005
42238
  };
42239
+ const parseReference = (prefixedId) => {
42240
+ if (!prefixedId.startsWith(REFERENCE_PREFIX))
42241
+ return null;
42242
+ const withoutPrefix = prefixedId.substring(REFERENCE_PREFIX.length);
42243
+ const colonIndex = withoutPrefix.indexOf(':');
42244
+ if (colonIndex === -1)
42245
+ return null;
42246
+ return {
42247
+ type: withoutPrefix.substring(0, colonIndex),
42248
+ id: withoutPrefix.substring(colonIndex + 1),
42249
+ };
42250
+ };
42251
+ const serializeReference = (reference) => {
42252
+ return addReferencePrefix(reference);
42253
+ };
41006
42254
  const ensureCleanFileId = (fileId) => {
41007
42255
  // Remove prefix if it exists to get clean file ID
41008
42256
  return removeFilePrefix(fileId);
41009
42257
  };
41010
42258
  const isFileId = (value) => value.startsWith(FILE_PREFIX);
41011
42259
  const isDocumentId = (value) => value.startsWith(DOCUMENT_PREFIX);
41012
- const isAnyFileRef = (value) => isFileId(value) || isDocumentId(value);
42260
+ const isReference = (value) => value.startsWith(REFERENCE_PREFIX);
42261
+ const isAnyFileRef = (value) => isFileId(value) || isDocumentId(value) || isReference(value);
41013
42262
  const hasDocumentMeta = (obj) => {
41014
42263
  const candidate = obj;
41015
42264
  if (!candidate || typeof candidate !== 'object' || !candidate.meta || typeof candidate.meta !== 'object') {
@@ -41113,7 +42362,11 @@ const createFileCastMiddleware = {
41113
42362
  if (isFileListItem(file)) {
41114
42363
  const processed = await processFileForStorage(file, ctx.id?.toString());
41115
42364
  if (processed) {
41116
- const prefixedId = processed.kind === 'document' ? addDocumentPrefix(processed.id) : addFilePrefix(processed.id);
42365
+ const prefixedId = processed.kind === 'document'
42366
+ ? addDocumentPrefix(processed.id)
42367
+ : processed.kind === 'reference'
42368
+ ? processed.id
42369
+ : addFilePrefix(processed.id);
41117
42370
  return prefixedId;
41118
42371
  }
41119
42372
  else {
@@ -41135,7 +42388,11 @@ const createFileCastMiddleware = {
41135
42388
  else if (isFileListItem(value)) {
41136
42389
  const processed = await processFileForStorage(value, ctx.id?.toString());
41137
42390
  if (processed) {
41138
- const prefixedId = processed.kind === 'document' ? addDocumentPrefix(processed.id) : addFilePrefix(processed.id);
42391
+ const prefixedId = processed.kind === 'document'
42392
+ ? addDocumentPrefix(processed.id)
42393
+ : processed.kind === 'reference'
42394
+ ? processed.id
42395
+ : addFilePrefix(processed.id);
41139
42396
  setValueByPath(ctx.data, keyPath, prefixedId);
41140
42397
  }
41141
42398
  else {
@@ -41197,22 +42454,31 @@ const createFileCastMiddleware = {
41197
42454
  await Promise.all(fileIdKeys.map(async (keyPath) => {
41198
42455
  const value = getValueByPath(resultData, keyPath);
41199
42456
  if (Array.isArray(value)) {
41200
- // Split file and document IDs
42457
+ // Split file, document, and reference IDs
41201
42458
  const fileIdList = [];
41202
42459
  const documentIdList = [];
42460
+ const referenceList = [];
41203
42461
  value.forEach((item) => {
41204
42462
  if (typeof item === 'string') {
41205
42463
  if (isFileId(item))
41206
42464
  fileIdList.push(removeFilePrefix(item));
41207
42465
  else if (isDocumentId(item))
41208
42466
  documentIdList.push(removeDocumentPrefix(item));
42467
+ else if (isReference(item)) {
42468
+ const ref = parseReference(item);
42469
+ if (ref)
42470
+ referenceList.push(ref);
42471
+ }
41209
42472
  }
41210
42473
  });
41211
42474
  try {
42475
+ // Fetch documents for references
42476
+ const referenceDocIds = referenceList.filter((ref) => ref.type === 'document').map((ref) => ref.id);
42477
+ const allDocIds = [...documentIdList, ...referenceDocIds];
41212
42478
  const [manyInfos, documents] = await Promise.all([
41213
42479
  fileIdList.length ? fileStorageService.findMany(fileIdList) : Promise.resolve([]),
41214
- documentIdList.length && documentService
41215
- ? documentService.findMany(documentIdList)
42480
+ allDocIds.length && documentService
42481
+ ? documentService.findMany(allDocIds)
41216
42482
  : Promise.resolve([]),
41217
42483
  ]);
41218
42484
  const infoMap = new Map(manyInfos.map((i) => [i.fileId, i]));
@@ -41254,6 +42520,33 @@ const createFileCastMiddleware = {
41254
42520
  source: { kind: 'fileId', value: actualDocId },
41255
42521
  };
41256
42522
  }
42523
+ if (typeof item === 'string' && isReference(item)) {
42524
+ const reference = parseReference(item);
42525
+ if (reference && reference.type === 'document' && documentService) {
42526
+ const doc = docMap.get(reference.id);
42527
+ if (doc) {
42528
+ const listItem = {
42529
+ id: reference.id,
42530
+ name: doc.name || 'Document',
42531
+ size: doc.size,
42532
+ status: 'uploaded',
42533
+ source: { kind: 'reference', value: reference },
42534
+ };
42535
+ // Expose full document object for downstream listeners/plugins
42536
+ listItem.documentData = doc;
42537
+ if (doc.metaDataForm)
42538
+ listItem.meta = doc.metaDataForm;
42539
+ return listItem;
42540
+ }
42541
+ }
42542
+ // Fallback for non-document references or when document not found
42543
+ return {
42544
+ id: reference?.id || 'unknown',
42545
+ name: 'Unknown Reference',
42546
+ status: 'remote',
42547
+ source: { kind: 'reference', value: reference || { id: 'unknown', type: 'unknown' } },
42548
+ };
42549
+ }
41257
42550
  return item;
41258
42551
  });
41259
42552
  setValueByPath(resultData, keyPath, convertedArray);
@@ -41339,6 +42632,55 @@ const createFileCastMiddleware = {
41339
42632
  });
41340
42633
  }
41341
42634
  }
42635
+ else if (isReference(value)) {
42636
+ const reference = parseReference(value);
42637
+ if (reference && reference.type === 'document' && documentService) {
42638
+ try {
42639
+ const docs = await documentService.findMany([reference.id]);
42640
+ const doc = docs?.[0];
42641
+ if (doc) {
42642
+ const listItem = {
42643
+ id: reference.id,
42644
+ name: doc.name || 'Document',
42645
+ size: doc.size,
42646
+ status: 'uploaded',
42647
+ source: { kind: 'reference', value: reference },
42648
+ };
42649
+ // Expose full document object for downstream listeners/plugins
42650
+ listItem.documentData = doc;
42651
+ if (doc.metaDataForm)
42652
+ listItem.meta = doc.metaDataForm;
42653
+ setValueByPath(resultData, keyPath, listItem);
42654
+ }
42655
+ else {
42656
+ setValueByPath(resultData, keyPath, {
42657
+ id: reference.id,
42658
+ name: 'Unknown Document',
42659
+ status: 'remote',
42660
+ source: { kind: 'reference', value: reference },
42661
+ });
42662
+ }
42663
+ }
42664
+ catch (error) {
42665
+ console.error('[file-cast] ❌ Failed to get reference document info', { keyPath, reference, error });
42666
+ setValueByPath(resultData, keyPath, {
42667
+ id: reference.id,
42668
+ name: 'Unknown Document',
42669
+ status: 'remote',
42670
+ source: { kind: 'reference', value: reference },
42671
+ });
42672
+ }
42673
+ }
42674
+ else {
42675
+ // Fallback for non-document references
42676
+ setValueByPath(resultData, keyPath, {
42677
+ id: reference?.id || 'unknown',
42678
+ name: 'Unknown Reference',
42679
+ status: 'remote',
42680
+ source: { kind: 'reference', value: reference || { id: 'unknown', type: 'unknown' } },
42681
+ });
42682
+ }
42683
+ }
41342
42684
  }
41343
42685
  }));
41344
42686
  }
@@ -41365,7 +42707,7 @@ const historyLoggerMiddleware = {
41365
42707
  target: { ops: ['create', 'update', 'delete'], order: 80 },
41366
42708
  execute: async (ctx, next) => {
41367
42709
  const sessionService = inject(AXPSessionService);
41368
- const versioning = inject(VersioningService);
42710
+ const versioning = inject(AXCVersioningService);
41369
42711
  // Capture previous for update/delete
41370
42712
  if (ctx.op === 'update' || ctx.op === 'delete') {
41371
42713
  try {
@@ -42348,6 +43690,148 @@ const signatureLoaderMiddleware = {
42348
43690
  //#endregion
42349
43691
  };
42350
43692
 
43693
+ //#region ---- Lock Guard Middleware ----
43694
+ /**
43695
+ * Middleware that prevents editing or deleting locked records.
43696
+ *
43697
+ * Supports two types of locks:
43698
+ * 1. 'user' lock: Automatic lock when edit popup is opened.
43699
+ * - Only the user who locked it can edit
43700
+ * - Other users cannot edit
43701
+ *
43702
+ * 2. 'admin' lock: Manual lock by admin for a specific duration or permanently.
43703
+ * - Even the admin who locked it cannot edit
43704
+ * - All users are blocked until lock expires (if expireAt is set)
43705
+ */
43706
+ const lockGuardMiddleware = {
43707
+ target: { ops: ['update', 'delete'], order: 10 },
43708
+ execute: async (ctx, next) => {
43709
+ const lockService = inject(AXPLockService);
43710
+ const session = inject(AXPSessionService);
43711
+ // Skip if no ID is provided (shouldn't happen for update/delete, but safety check)
43712
+ if (!ctx.id) {
43713
+ await next();
43714
+ return;
43715
+ }
43716
+ // First, check for 'admin' lock (highest priority - blocks everyone including the admin who locked it)
43717
+ try {
43718
+ const adminLockExists = await lockService.check({
43719
+ refId: ctx.id,
43720
+ refType: ctx.entityName,
43721
+ type: 'admin'
43722
+ });
43723
+ if (adminLockExists) {
43724
+ try {
43725
+ const adminLockInfo = await lockService.getInfo({
43726
+ refId: ctx.id,
43727
+ refType: ctx.entityName,
43728
+ type: 'admin'
43729
+ });
43730
+ if (adminLockInfo) {
43731
+ // Check if admin lock has expired
43732
+ let isExpired = false;
43733
+ if (adminLockInfo.expireAt) {
43734
+ const now = new Date();
43735
+ const expireDate = new Date(adminLockInfo.expireAt);
43736
+ isExpired = now > expireDate;
43737
+ }
43738
+ // If admin lock exists and hasn't expired, block everyone (including the admin who locked it)
43739
+ if (!isExpired) {
43740
+ throw new AXPMiddlewareAbortError('This record is locked by administrator and cannot be edited or deleted.', {
43741
+ status: 409,
43742
+ code: 'RECORD_ADMIN_LOCKED',
43743
+ details: {
43744
+ entity: ctx.entityName,
43745
+ id: ctx.id,
43746
+ lockedBy: adminLockInfo.lockedBy,
43747
+ lockType: adminLockInfo.type,
43748
+ expireAt: adminLockInfo.expireAt,
43749
+ operation: ctx.op,
43750
+ },
43751
+ });
43752
+ }
43753
+ }
43754
+ }
43755
+ catch (error) {
43756
+ // If getInfo throws an error (e.g., lock not found), continue to check user lock
43757
+ if (error instanceof AXPMiddlewareAbortError) {
43758
+ throw error;
43759
+ }
43760
+ // Otherwise, ignore and continue
43761
+ }
43762
+ }
43763
+ }
43764
+ catch (error) {
43765
+ // If it's already an AXPMiddlewareAbortError, re-throw it
43766
+ if (error instanceof AXPMiddlewareAbortError) {
43767
+ throw error;
43768
+ }
43769
+ // Otherwise, continue to check user lock
43770
+ }
43771
+ // Second, check for 'user' lock (only blocks other users, not the user who locked it)
43772
+ try {
43773
+ const userLockExists = await lockService.check({
43774
+ refId: ctx.id,
43775
+ refType: ctx.entityName,
43776
+ type: 'user'
43777
+ });
43778
+ if (userLockExists) {
43779
+ try {
43780
+ const userLockInfo = await lockService.getInfo({
43781
+ refId: ctx.id,
43782
+ refType: ctx.entityName,
43783
+ type: 'user'
43784
+ });
43785
+ if (userLockInfo) {
43786
+ // Check if user lock has expired
43787
+ let isExpired = false;
43788
+ if (userLockInfo.expireAt) {
43789
+ const now = new Date();
43790
+ const expireDate = new Date(userLockInfo.expireAt);
43791
+ isExpired = now > expireDate;
43792
+ }
43793
+ // If user lock exists and hasn't expired, check if current user is the one who locked it
43794
+ if (!isExpired) {
43795
+ // If current user is not the one who locked it, prevent the operation
43796
+ if (session.user && userLockInfo.lockedBy.id !== session.user.id) {
43797
+ throw new AXPMiddlewareAbortError('This record is locked by another user and cannot be edited or deleted.', {
43798
+ status: 409,
43799
+ code: 'RECORD_USER_LOCKED',
43800
+ details: {
43801
+ entity: ctx.entityName,
43802
+ id: ctx.id,
43803
+ lockedBy: userLockInfo.lockedBy,
43804
+ lockType: userLockInfo.type,
43805
+ operation: ctx.op,
43806
+ },
43807
+ });
43808
+ }
43809
+ // If current user is the one who locked it, allow the operation (continue to next())
43810
+ }
43811
+ }
43812
+ }
43813
+ catch (error) {
43814
+ // If getInfo throws an error (e.g., lock not found), continue
43815
+ if (error instanceof AXPMiddlewareAbortError) {
43816
+ throw error;
43817
+ }
43818
+ // Otherwise, ignore and continue
43819
+ }
43820
+ }
43821
+ }
43822
+ catch (error) {
43823
+ // If it's already an AXPMiddlewareAbortError, re-throw it
43824
+ if (error instanceof AXPMiddlewareAbortError) {
43825
+ throw error;
43826
+ }
43827
+ // Otherwise, continue
43828
+ }
43829
+ // If no blocking locks found, proceed with the operation
43830
+ await next();
43831
+ },
43832
+ };
43833
+ //#endregion
43834
+
42351
43835
  class AXCMiddlewaresModule {
42352
43836
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.10", ngImport: i0, type: AXCMiddlewaresModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
42353
43837
  static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.10", ngImport: i0, type: AXCMiddlewaresModule }); }
@@ -42366,6 +43850,7 @@ class AXCMiddlewaresModule {
42366
43850
  { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: primaryMiddleware },
42367
43851
  { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: historyLoggerMiddleware },
42368
43852
  { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: signatureLoaderMiddleware },
43853
+ { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: lockGuardMiddleware },
42369
43854
  // Sample entity event listener to show logs for all entity.* events
42370
43855
  //{ provide: AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER, multi: true, useValue: AXCMockEntityLogListener },
42371
43856
  ] }); }
@@ -42391,6 +43876,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.10", ngImpo
42391
43876
  { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: primaryMiddleware },
42392
43877
  { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: historyLoggerMiddleware },
42393
43878
  { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: signatureLoaderMiddleware },
43879
+ { provide: AXP_ENTITY_STORAGE_MIDDLEWARE, multi: true, useValue: lockGuardMiddleware },
42394
43880
  // Sample entity event listener to show logs for all entity.* events
42395
43881
  //{ provide: AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER, multi: true, useValue: AXCMockEntityLogListener },
42396
43882
  ],
@@ -42670,5 +44156,5 @@ const AXCMockEntityLogListener = {
42670
44156
  * Generated bundle index. Do not edit.
42671
44157
  */
42672
44158
 
42673
- export { APPLICATIONS, AXCAppTermDataSeeder, AXCAppVersionDataSeeder, AXCApplicationDataSeeder, AXCApplicationManagementMockModule, AXCAssessmentManagementMockModule, AXCAuthMockModule, AXCCalendarDataSeeder, AXCCalendarEventDataSeeder, AXCCalendarManagementMockModule, AXCCommonMockModule, AXCContactManagementMockModule, AXCContentManagementMockModule, AXCConversationMockModule, AXCCustomerManagementMockModule, AXCDashboardManagementMockModule, AXCDataManagementMockModule, AXCDexieEntityStorageService, AXCDocumentManagementMockModule, AXCEditionDataSeeder, AXCFeatureDataSeeder, AXCFileStorageService, AXCFormTemplateManagementMockModule, AXCGlobalVariablesDataSeeder, AXCGoogleStrategyMock, AXCHelpDeskMockModule, AXCHumanCapitalManagementMockModule, AXCIdentifierManagementMockModule, AXCJsaSeeder, AXCLocaleManagementMockModule, AXCLocationManagementMockModule, AXCLockService, AXCLogManagementMockModule, AXCLogReportCategoryProvider, AXCLogReportDefinitionProvider, AXCMeetingManagementMockModule, AXCMetaDataDefinitionDataSeeder, AXCMiddlewaresModule, AXCMockEntityLogListener, AXCMockModule, AXCModuleDataSeeder, AXCNotificationManagementMockModule, AXCOrganizationManagementMockModule, AXCPartyManagementMockModule, AXCPlatformManagementMockModule, AXCProjectManagementMockModule, AXCQueryCategoryMetadataInheritanceQuery, AXCReportManagementMockModule, AXCSecurityManagementMockModule, AXCTaskManagementMockModule, AXCTrainingManagementMockModule, AXCUserPassStrategyMock, AXCVersionDB, AXCWorkflowExecutionDB, AXCWorkflowExecutionService, AXCWorkflowManagementMockModule, AXC_LOG_REPORT_CATEGORY_PROVIDER, AXC_LOG_REPORT_DEFINITION_PROVIDER, AXMAiResponderService, AXMBusinessUnitDataSeeder, AXMCalendarEventTypeSeeder, AXMCollaboratorDataSeeder, AXMEmployeeDataSeeder, AXMEmployeeSkillDataSeeder, AXMEmployeeSkillsCategoryProvider, AXMEmployeeSkillsReportDefinitionProvider, AXMEmploymentTypeDataSeeder, AXMFormDataSourcesProvider, AXMIndustryDataSeeder, AXMLeaveRequestDataSeeder, AXMMeetingDataSeeder, AXMMeetingFilesDataSeeder, AXMMeetingParticipantDataSeeder, AXMMeetingRoleTypeDataSeeder, AXMMeetingSessionDataSeeder, AXMMeetingTypeDataSeeder, AXMMeetingTypeFileTemplateDataSeeder, AXMPositionAssignmentDataSeeder, AXMPositionDataSeeder, AXMPublicationDataSeeder, AXMQuestionBankItemCategoryDataSeeder, AXMQuestionBankItemDataSeeder, AXMQuestionnaireCategoryDataSeeder, AXMQuestionnaireDataSeeder, AXMReportCategoryDataSeeder, AXMReportDefinitionDataSeeder, AXMReportExecuteCommand, AXMReportMockDataService, AXMResponseEntryDataSeeder, AXMResponseSessionDataSeeder, AXMResponsibilityDataSeeder, AXMRoleDataSeeder, AXMSkillDataSeeder, AXMSkillLevelDataSeeder, AXMTagDataSeeder, AXMTeamDataSeeder, AXM_EMPLOYEE_SKILLS_CATEGORY_PROVIDER, AXM_EMPLOYEE_SKILLS_DEFINITION_PROVIDER, AXPDashboardDataSeeder, AXPIdentifierDB, AXPMessageDataSeeder, AXPMockChecksumProvider, AXPMockClockProvider, AXPMockIdentifierService, AXPMockLookupProvider, AXPMockPolicyProvider, AXPMockSequenceProvider, AXPRoomDataSeeder, AXPSecurityManagementRoleDataSeeder, AXPSecurityManagementUserDataSeeder, AXPTaskBoardPlatformManagementTaskProvider, AXPTaskBoardProjectManagementTaskProvider, AXQEmployeeSkillsLevelPercentagesQuery, AXQEmployeeSkillsLevelsQuery, AXQEmployeeSkillsListQuery, AXQEmployeeSkillsSkillPercentagesQuery, AXQEmployeeSkillsStatsQuery, AXQEmployeeSkillsTrendQuery, AXVChangeType, BUSINESS_UNITS_MOCK, DASHBOARDS, EDITIONS, EMPLOYEES_MOCK, EMPLOYEE_SKILLS_MOCK, EMPLOYMENT_TYPES_MOCK, FEATURES, GLOBAL_VARIABLES, LEAVE_REQUESTS_MOCK, MODULES, POSITIONS_CATEGORY_MOCK, POSITIONS_MOCK, POSITION_ASSIGNMENTS_MOCK, QUESTIONNAIRE_CATEGORY_MOCK, QUESTION_BANK_ITEM_CATEGORY_MOCK, RESPONSIBILITIES_CATEGORY_MOCK, RESPONSIBILITIES_MOCK, ROLES_CATEGORY_MOCK, ROLES_MOCK, SKILLS_CATEGORY_MOCK, SKILLS_MOCK, SKILL_LEVELS_MOCK, TAGS_MOCK, TASKS, TASK_STATUSES, TASK_TEMPLATES, TASK_TYPES, TEAMS_MOCK, VersioningService, applications, auditLoggerMiddleware, axVersionDB, axWorkflowExecutionDB, calendarEventMock, calendarEventTypeMockData, calendarMock, childCountMiddleware, collaboratorMock, computeDiff, createAndSaveDashboardForUser, createDashboardForUser, createFileCastMiddleware, findContactMethod, findEmployeeById, findPartyById, generateUserDashboard, historyLoggerMiddleware, identifierCommitMiddleware, lookupResolverMiddleware, meetingFilesMock, meetingIds, meetingMock, meetingParticipantMock, meetingRoleTypeMock, meetingSessionMock, meetingTimeSlotMock, meetingTypeFileTemplateMock, meetingTypeMock, mergeDetailRelationMiddleware, mockRoleDefinitions, mockUsers, normalizeAnyFileArrayForView, normalizeSnapshotFileFieldsForView, participantIds, primaryMiddleware, publicationMock, questionBankItemMock, questionnaireMock, responseEntryMock, responseSessionMock, signatureLoaderMiddleware, tenantsMock, toUiRows };
44159
+ export { APPLICATIONS, AXCAppTermDataSeeder, AXCAppVersionDataSeeder, AXCApplicationDataSeeder, AXCApplicationManagementMockModule, AXCAssessmentManagementMockModule, AXCAuthMockModule, AXCCalendarDataSeeder, AXCCalendarEventDataSeeder, AXCCalendarManagementMockModule, AXCCommonMockModule, AXCContactManagementMockModule, AXCContentManagementMockModule, AXCConversationMockModule, AXCCustomerManagementMockModule, AXCDashboardManagementMockModule, AXCDataManagementMockModule, AXCDexieEntityStorageService, AXCDocumentManagementMockModule, AXCEditionDataSeeder, AXCFeatureDataSeeder, AXCFileStorageService, AXCFormTemplateManagementMockModule, AXCGlobalVariablesDataSeeder, AXCGoogleStrategyMock, AXCHelpDeskMockModule, AXCHumanCapitalManagementMockModule, AXCIdentifierManagementMockModule, AXCJsaSeeder, AXCLocaleManagementMockModule, AXCLocationManagementMockModule, AXCLockService, AXCLogManagementMockModule, AXCLogReportCategoryProvider, AXCLogReportDefinitionProvider, AXCMeetingManagementMockModule, AXCMetaDataDefinitionDataSeeder, AXCMiddlewaresModule, AXCMockEntityLogListener, AXCMockModule, AXCModuleDataSeeder, AXCNotificationManagementMockModule, AXCOrganizationManagementMockModule, AXCPartyManagementMockModule, AXCPlatformManagementMockModule, AXCProjectManagementMockModule, AXCQueryCategoryMetadataInheritanceQuery, AXCReportManagementMockModule, AXCSecurityManagementMockModule, AXCTaskManagementMockModule, AXCTrainingManagementMockModule, AXCUserPassStrategyMock, AXCVersionDB, AXCVersioningService, AXCWorkflowDefinitionDataSeeder, AXCWorkflowExecutionDB, AXCWorkflowExecutionService, AXCWorkflowManagementMockModule, AXC_LOG_REPORT_CATEGORY_PROVIDER, AXC_LOG_REPORT_DEFINITION_PROVIDER, AXMAiResponderService, AXMBusinessUnitDataSeeder, AXMCalendarEventTypeSeeder, AXMCollaboratorDataSeeder, AXMEmployeeDataSeeder, AXMEmployeeSkillDataSeeder, AXMEmployeeSkillsCategoryProvider, AXMEmployeeSkillsReportDefinitionProvider, AXMEmploymentTypeDataSeeder, AXMFormDataSourcesProvider, AXMIndustryDataSeeder, AXMLeaveRequestDataSeeder, AXMMeetingDataSeeder, AXMMeetingFilesDataSeeder, AXMMeetingParticipantDataSeeder, AXMMeetingRoleTypeDataSeeder, AXMMeetingSessionDataSeeder, AXMMeetingTypeDataSeeder, AXMMeetingTypeFileTemplateDataSeeder, AXMPositionAssignmentDataSeeder, AXMPositionDataSeeder, AXMPublicationDataSeeder, AXMQuestionBankItemCategoryDataSeeder, AXMQuestionBankItemDataSeeder, AXMQuestionnaireCategoryDataSeeder, AXMQuestionnaireDataSeeder, AXMReportCategoryDataSeeder, AXMReportDefinitionDataSeeder, AXMReportExecuteCommand, AXMReportMockDataService, AXMResponseEntryDataSeeder, AXMResponseSessionDataSeeder, AXMResponsibilityDataSeeder, AXMRoleDataSeeder, AXMSkillDataSeeder, AXMSkillLevelDataSeeder, AXMTagDataSeeder, AXMTeamDataSeeder, AXM_EMPLOYEE_SKILLS_CATEGORY_PROVIDER, AXM_EMPLOYEE_SKILLS_DEFINITION_PROVIDER, AXPDashboardDataSeeder, AXPIdentifierDB, AXPMessageDataSeeder, AXPMockChecksumProvider, AXPMockClockProvider, AXPMockIdentifierService, AXPMockLookupProvider, AXPMockPolicyProvider, AXPMockSequenceProvider, AXPRoomDataSeeder, AXPSecurityManagementRoleDataSeeder, AXPSecurityManagementUserDataSeeder, AXPTaskBoardPlatformManagementTaskProvider, AXPTaskBoardProjectManagementTaskProvider, AXQEmployeeSkillsLevelPercentagesQuery, AXQEmployeeSkillsLevelsQuery, AXQEmployeeSkillsListQuery, AXQEmployeeSkillsSkillPercentagesQuery, AXQEmployeeSkillsStatsQuery, AXQEmployeeSkillsTrendQuery, AXVChangeType, BUSINESS_UNITS_MOCK, CheckPermissionActivity, DASHBOARDS, EDITIONS, EMPLOYEES_MOCK, EMPLOYEE_SKILLS_MOCK, EMPLOYMENT_TYPES_MOCK, ExecuteCommandActivity, ExecuteQueryActivity, FEATURES, GLOBAL_VARIABLES, LEAVE_REQUESTS_MOCK, MODULES, POSITIONS_CATEGORY_MOCK, POSITIONS_MOCK, POSITION_ASSIGNMENTS_MOCK, QUESTIONNAIRE_CATEGORY_MOCK, QUESTION_BANK_ITEM_CATEGORY_MOCK, RESPONSIBILITIES_CATEGORY_MOCK, RESPONSIBILITIES_MOCK, ROLES_CATEGORY_MOCK, ROLES_MOCK, SKILLS_CATEGORY_MOCK, SKILLS_MOCK, SKILL_LEVELS_MOCK, TAGS_MOCK, TASKS, TASK_STATUSES, TASK_TEMPLATES, TASK_TYPES, TEAMS_MOCK, applications, auditLoggerMiddleware, axVersionDB, axWorkflowExecutionDB, calendarEventMock, calendarEventTypeMockData, calendarMock, childCountMiddleware, collaboratorMock, computeDiff, createAndSaveDashboardForUser, createDashboardForUser, createFileCastMiddleware, findContactMethod, findEmployeeById, findPartyById, generateUserDashboard, historyLoggerMiddleware, identifierCommitMiddleware, lockGuardMiddleware, lookupResolverMiddleware, meetingFilesMock, meetingIds, meetingMock, meetingParticipantMock, meetingRoleTypeMock, meetingSessionMock, meetingTimeSlotMock, meetingTypeFileTemplateMock, meetingTypeMock, mergeDetailRelationMiddleware, mockRoleDefinitions, mockUsers, normalizeAnyFileArrayForView, normalizeSnapshotFileFieldsForView, participantIds, primaryMiddleware, provideWorkflowActivities, publicationMock, questionBankItemMock, questionnaireMock, responseEntryMock, responseSessionMock, signatureLoaderMiddleware, tenantsMock, toUiRows, workflowDefinitionEntityMock, workflowDefinitionIds, workflowDefinitionMock };
42674
44160
  //# sourceMappingURL=acorex-connectivity-mock.mjs.map