@acorex-platform/framework-server 0.0.56 → 0.0.58

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/jql/mongodb/src/lib/jql-mongodb.engine.d.ts.map +1 -1
  2. package/jql/mongodb/src/lib/jql-mongodb.engine.js +8 -12
  3. package/jql/mongodb/src/lib/jql-mongodb.engine.js.map +1 -1
  4. package/jql/schema/src/lib/generated/plugin-contributions.bootstrap.d.ts.map +1 -1
  5. package/jql/schema/src/lib/generated/plugin-contributions.bootstrap.js +60 -0
  6. package/jql/schema/src/lib/generated/plugin-contributions.bootstrap.js.map +1 -1
  7. package/jql/schema/src/lib/generated/widget-data-types.bootstrap.d.ts.map +1 -1
  8. package/jql/schema/src/lib/generated/widget-data-types.bootstrap.js +0 -1
  9. package/jql/schema/src/lib/generated/widget-data-types.bootstrap.js.map +1 -1
  10. package/package.json +2 -2
  11. package/workflow/src/lib/middlewares/workflow-definition-cache.middleware.d.ts +17 -0
  12. package/workflow/src/lib/middlewares/workflow-definition-cache.middleware.d.ts.map +1 -0
  13. package/workflow/src/lib/middlewares/workflow-definition-cache.middleware.js +35 -0
  14. package/workflow/src/lib/middlewares/workflow-definition-cache.middleware.js.map +1 -0
  15. package/workflow/src/lib/runtime/jql-workflow-execution-store.service.d.ts.map +1 -1
  16. package/workflow/src/lib/runtime/jql-workflow-execution-store.service.js +0 -12
  17. package/workflow/src/lib/runtime/jql-workflow-execution-store.service.js.map +1 -1
  18. package/workflow/src/lib/runtime/workflow-definition-runtime-cache.d.ts +12 -0
  19. package/workflow/src/lib/runtime/workflow-definition-runtime-cache.d.ts.map +1 -0
  20. package/workflow/src/lib/runtime/workflow-definition-runtime-cache.js +30 -0
  21. package/workflow/src/lib/runtime/workflow-definition-runtime-cache.js.map +1 -0
  22. package/workflow/src/lib/runtime/workflow-engine.service.d.ts +15 -1
  23. package/workflow/src/lib/runtime/workflow-engine.service.d.ts.map +1 -1
  24. package/workflow/src/lib/runtime/workflow-engine.service.js +119 -52
  25. package/workflow/src/lib/runtime/workflow-engine.service.js.map +1 -1
  26. package/workflow/src/lib/runtime/workflow-local-dismiss.d.ts +8 -0
  27. package/workflow/src/lib/runtime/workflow-local-dismiss.d.ts.map +1 -0
  28. package/workflow/src/lib/runtime/workflow-local-dismiss.js +80 -0
  29. package/workflow/src/lib/runtime/workflow-local-dismiss.js.map +1 -0
  30. package/workflow/src/lib/runtime/workflow-runtime.types.d.ts +15 -0
  31. package/workflow/src/lib/runtime/workflow-runtime.types.d.ts.map +1 -1
  32. package/workflow/src/lib/runtime/workflow-runtime.types.js.map +1 -1
  33. package/workflow/src/lib/workflow.module.d.ts.map +1 -1
  34. package/workflow/src/lib/workflow.module.js +9 -0
  35. package/workflow/src/lib/workflow.module.js.map +1 -1
@@ -10,6 +10,8 @@ const uuid_util_1 = require("../utils/uuid.util");
10
10
  const workflow_management_const_1 = require("./workflow-management.const");
11
11
  const workflow_engine_errors_1 = require("./workflow-engine.errors");
12
12
  const workflow_activity_definition_service_1 = require("./workflow-activity-definition.service");
13
+ const workflow_definition_runtime_cache_1 = require("./workflow-definition-runtime-cache");
14
+ const workflow_local_dismiss_1 = require("./workflow-local-dismiss");
13
15
  const workflow_activity_registry_1 = require("../activities/workflow-activity.registry");
14
16
  const workflow_expression_evaluator_service_1 = require("./workflow-expression-evaluator.service");
15
17
  const workflow_expression_scope_service_1 = require("./workflow-expression-scope.service");
@@ -26,7 +28,7 @@ const AXP_WORKFLOW_TASK_CONTEXT_TITLE_PARTS_KEY = '_taskTitleParts';
26
28
  */
27
29
  let BackendWorkflowEngineService = BackendWorkflowEngineService_1 = class BackendWorkflowEngineService {
28
30
  //#region ---- Services & Dependencies ----
29
- constructor(store, entityStorageService, activityDefinitionService, expressionScopeService, expressionEvaluator, sessionService, activityRegistry) {
31
+ constructor(store, entityStorageService, activityDefinitionService, expressionScopeService, expressionEvaluator, sessionService, activityRegistry, definitionCache) {
30
32
  this.store = store;
31
33
  this.entityStorageService = entityStorageService;
32
34
  this.activityDefinitionService = activityDefinitionService;
@@ -34,6 +36,7 @@ let BackendWorkflowEngineService = BackendWorkflowEngineService_1 = class Backen
34
36
  this.expressionEvaluator = expressionEvaluator;
35
37
  this.sessionService = sessionService;
36
38
  this.activityRegistry = activityRegistry;
39
+ this.definitionCache = definitionCache;
37
40
  //#endregion
38
41
  //#region ---- Task Token Management ----
39
42
  /**
@@ -86,9 +89,10 @@ let BackendWorkflowEngineService = BackendWorkflowEngineService_1 = class Backen
86
89
  * Load workflow definition by name from entity storage.
87
90
  */
88
91
  async getDefinition(workflowId) {
89
- console.log(`[BackendWorkflowRuntime] 🔍 Loading workflow definition: ${workflowId}`);
90
- // Query entity storage by name field (not id)
91
- console.log(`[BackendWorkflowRuntime] 🔄 Fallback: Querying entity storage by name field: ${workflowId}`);
92
+ const cached = this.definitionCache.get(workflowId);
93
+ if (cached) {
94
+ return cached;
95
+ }
92
96
  try {
93
97
  const result = await this.entityStorageService.query('WorkflowManagement.WorkflowDefinition', {
94
98
  skip: 0,
@@ -99,16 +103,18 @@ let BackendWorkflowEngineService = BackendWorkflowEngineService_1 = class Backen
99
103
  value: workflowId,
100
104
  },
101
105
  });
102
- if (result.items && result.items.length > 0) {
103
- const entity = result.items[0];
104
- console.log(`[BackendWorkflowRuntime] ✅ Found definition via entity storage: ${workflowId}`);
105
- return entity;
106
+ const entity = result.items?.[0];
107
+ if (entity) {
108
+ const definition = entity;
109
+ this.definitionCache.set(workflowId, definition);
110
+ return definition;
106
111
  }
107
112
  }
108
113
  catch (error) {
109
- console.error(`[BackendWorkflowRuntime] ❌ Error querying entity storage:`, error);
114
+ console.error(`[BackendWorkflowRuntime] Error querying workflow definition "${workflowId}":`, error);
115
+ return null;
110
116
  }
111
- console.error(`[BackendWorkflowRuntime] ❌ Workflow definition not found: ${workflowId}`);
117
+ console.error(`[BackendWorkflowRuntime] Workflow definition not found: ${workflowId}`);
112
118
  return null;
113
119
  }
114
120
  /**
@@ -333,6 +339,7 @@ let BackendWorkflowEngineService = BackendWorkflowEngineService_1 = class Backen
333
339
  entityRefType: entityRefType || null,
334
340
  };
335
341
  let stored = false;
342
+ let keepInstanceInMemory = false;
336
343
  try {
337
344
  return await (0, workflow_trigger_guard_1.runInsideWorkflowEngine)(() => this.store.runWithoutPersist(async () => {
338
345
  await this.store.addInstance(instance);
@@ -395,6 +402,11 @@ let BackendWorkflowEngineService = BackendWorkflowEngineService_1 = class Backen
395
402
  if (effectiveExecutionMode === 'frontend' ||
396
403
  effectiveExecutionMode === 'both') {
397
404
  const pendingTask = await this.createTaskFromActivity(currentActivity, state);
405
+ const localDismiss = (0, workflow_local_dismiss_1.resolveWorkflowLocalDismiss)(workflow, currentActivity.id);
406
+ if (localDismiss) {
407
+ pendingTask.localDismiss = localDismiss;
408
+ keepInstanceInMemory = true;
409
+ }
398
410
  // Use local taskType (may be forced to human-task for workflow-activity:human-task) so bookmark and UI see correct type
399
411
  const resolvedTaskTypeForBookmark = taskType === 'human-task' || pendingTask.taskType === 'human-task'
400
412
  ? 'human-task'
@@ -581,7 +593,7 @@ let BackendWorkflowEngineService = BackendWorkflowEngineService_1 = class Backen
581
593
  }));
582
594
  }
583
595
  finally {
584
- if (stored) {
596
+ if (stored && !keepInstanceInMemory) {
585
597
  const current = await this.store.getInstance(instanceId);
586
598
  if (current) {
587
599
  await this.writeInstanceProjection(current, workflow, true);
@@ -2050,6 +2062,42 @@ let BackendWorkflowEngineService = BackendWorkflowEngineService_1 = class Backen
2050
2062
  };
2051
2063
  }
2052
2064
  }
2065
+ /**
2066
+ * The task row was just created with this user and the same display name.
2067
+ * Skip the follow-up read and update.
2068
+ */
2069
+ linkedTaskAssigneeAlreadyStamped(instance, assignUserFields) {
2070
+ const userId = assignUserFields.assignUser?.id?.trim();
2071
+ const displayName = assignUserFields.assignUserRef?.displayName?.trim();
2072
+ if (!userId || !displayName) {
2073
+ return false;
2074
+ }
2075
+ const variables = instance.workflowState
2076
+ ?.variables ?? {};
2077
+ const stamped = variables['assigneeUserId'];
2078
+ if (stamped == null || String(stamped).trim() !== userId) {
2079
+ return false;
2080
+ }
2081
+ return this.readWorkflowAssigneeDisplayName(variables) === displayName;
2082
+ }
2083
+ readWorkflowAssigneeDisplayName(variables) {
2084
+ const user = variables['assigneeUser'];
2085
+ if (user && typeof user === 'object' && 'displayName' in user) {
2086
+ const name = String(user.displayName ?? '').trim();
2087
+ if (name) {
2088
+ return name;
2089
+ }
2090
+ }
2091
+ const employee = variables['assigneeEmployee'];
2092
+ if (employee && typeof employee === 'object' && 'person' in employee) {
2093
+ const person = employee.person;
2094
+ const name = String(person?.fullName ?? '').trim();
2095
+ if (name) {
2096
+ return name;
2097
+ }
2098
+ }
2099
+ return undefined;
2100
+ }
2053
2101
  /**
2054
2102
  * Mirror the current workflow human-task assignee onto the linked Task row
2055
2103
  * so entity lists (e.g. project Tasks) match the task board popover.
@@ -2209,39 +2257,65 @@ let BackendWorkflowEngineService = BackendWorkflowEngineService_1 = class Backen
2209
2257
  */
2210
2258
  async writeInstanceProjection(instance, definition, insert) {
2211
2259
  if (insert) {
2212
- await this.saveInstanceToEntityService(instance, definition);
2260
+ await this.saveInstanceToEntityService(instance, definition, { assumeNew: true });
2213
2261
  return;
2214
2262
  }
2215
2263
  await this.updateInstanceInEntityService(instance, definition);
2216
2264
  }
2265
+ /**
2266
+ * Bookmark body is stored once. Readers accept payloadJson without a second parsed copy.
2267
+ */
2268
+ persistedBookmarks(bookmarks) {
2269
+ return bookmarks.map((bookmark) => ({
2270
+ id: bookmark.id,
2271
+ activityId: bookmark.activityId,
2272
+ activityInstanceId: bookmark.activityId,
2273
+ type: bookmark.type,
2274
+ payloadJson: bookmark.payloadJson,
2275
+ consumed: bookmark.isConsumed,
2276
+ isConsumed: bookmark.isConsumed,
2277
+ createdAt: bookmark.createdAt,
2278
+ }));
2279
+ }
2280
+ async resolveProjectionAssignUserFields(instance, activeBookmarks) {
2281
+ const fromVariables = this.assignUserFieldsFromVariables(instance);
2282
+ if (fromVariables) {
2283
+ return fromVariables;
2284
+ }
2285
+ return this.resolveAssignUserLookupFields(this.resolvePrimaryAssignUserId(instance, activeBookmarks));
2286
+ }
2287
+ assignUserFieldsFromVariables(instance) {
2288
+ const properties = (instance.workflowState?.properties ?? {});
2289
+ const userId = typeof properties['assigneeUserId'] === 'string' ? properties['assigneeUserId'].trim() : '';
2290
+ const displayName = this.readWorkflowAssigneeDisplayName(properties);
2291
+ if (!userId || !displayName) {
2292
+ return undefined;
2293
+ }
2294
+ return {
2295
+ assignUser: { id: userId },
2296
+ assignUserRef: { id: userId, displayName },
2297
+ };
2298
+ }
2217
2299
  /**
2218
2300
  * Save workflow instance to entity service for entity-based access.
2219
2301
  */
2220
- async saveInstanceToEntityService(instance, predefined) {
2302
+ async saveInstanceToEntityService(instance, predefined, options) {
2221
2303
  try {
2222
2304
  // Get active bookmarks for this instance to include in entity model
2223
2305
  const activeBookmarks = await this.getActiveBookmarks(instance.id);
2224
2306
  // Add bookmarks to instance for entity storage access
2225
2307
  const instanceWithBookmarks = {
2226
2308
  ...instance,
2227
- bookmarks: activeBookmarks.map((b) => ({
2228
- id: b.id,
2229
- activityId: b.activityId,
2230
- activityInstanceId: b.activityId, // For compatibility
2231
- type: b.type,
2232
- payload: b.payloadJson ? JSON.parse(b.payloadJson) : null,
2233
- payloadJson: b.payloadJson,
2234
- consumed: b.isConsumed,
2235
- isConsumed: b.isConsumed,
2236
- createdAt: b.createdAt,
2237
- })),
2309
+ bookmarks: this.persistedBookmarks(activeBookmarks),
2238
2310
  };
2239
2311
  const definition = predefined ?? (await this.getDefinition(instance.definitionId));
2240
2312
  const overview = this.computeOverviewDisplayFields(instance, definition);
2241
2313
  const runtimeDetails = this.computeRuntimeDetails(instance, definition, activeBookmarks);
2242
2314
  const workflowVariablesTable = this.computeWorkflowVariablesTable(instance, definition);
2243
- const assignUserFields = await this.resolveAssignUserLookupFields(this.resolvePrimaryAssignUserId(instance, activeBookmarks));
2244
- await this.syncLinkedTaskAssignee(instance, assignUserFields);
2315
+ const assignUserFields = await this.resolveProjectionAssignUserFields(instance, activeBookmarks);
2316
+ if (!this.linkedTaskAssigneeAlreadyStamped(instance, assignUserFields)) {
2317
+ await this.syncLinkedTaskAssignee(instance, assignUserFields);
2318
+ }
2245
2319
  const scopeInfo = this.getSessionScopeInfo();
2246
2320
  const entityModel = {
2247
2321
  id: instance.id,
@@ -2271,19 +2345,19 @@ let BackendWorkflowEngineService = BackendWorkflowEngineService_1 = class Backen
2271
2345
  ...(scopeInfo ? { scopeInfo } : {}),
2272
2346
  };
2273
2347
  const entityName = 'WorkflowManagement.WorkflowInstance';
2274
- // Check if instance already exists
2275
- try {
2276
- const existing = await this.entityStorageService.getOneAsEngine(entityName, entityModel.id);
2277
- if (existing) {
2278
- // Already exists - don't insert again, will be updated later
2279
- console.log('[AXCWorkflowExecutionService] â„šī¸ Instance already exists in entity service, will be updated later', {
2280
- instanceId: instance.id,
2281
- });
2282
- return;
2348
+ if (!options?.assumeNew) {
2349
+ try {
2350
+ const existing = await this.entityStorageService.getOneAsEngine(entityName, entityModel.id);
2351
+ if (existing) {
2352
+ console.log('[AXCWorkflowExecutionService] â„šī¸ Instance already exists in entity service, will be updated later', {
2353
+ instanceId: instance.id,
2354
+ });
2355
+ return;
2356
+ }
2357
+ }
2358
+ catch {
2359
+ // Instance doesn't exist - proceed with insert
2283
2360
  }
2284
- }
2285
- catch (getError) {
2286
- // Instance doesn't exist - proceed with insert
2287
2361
  }
2288
2362
  // Insert new instance
2289
2363
  await this.entityStorageService.insertOneAsEngine(entityName, entityModel);
@@ -2309,24 +2383,16 @@ let BackendWorkflowEngineService = BackendWorkflowEngineService_1 = class Backen
2309
2383
  // Add bookmarks to instance for entity storage access
2310
2384
  const instanceWithBookmarks = {
2311
2385
  ...instance,
2312
- bookmarks: activeBookmarks.map((b) => ({
2313
- id: b.id,
2314
- activityId: b.activityId,
2315
- activityInstanceId: b.activityId, // For compatibility
2316
- type: b.type,
2317
- payload: b.payloadJson ? JSON.parse(b.payloadJson) : null,
2318
- payloadJson: b.payloadJson,
2319
- consumed: b.isConsumed,
2320
- isConsumed: b.isConsumed,
2321
- createdAt: b.createdAt,
2322
- })),
2386
+ bookmarks: this.persistedBookmarks(activeBookmarks),
2323
2387
  };
2324
2388
  const definition = predefined ?? (await this.getDefinition(instance.definitionId));
2325
2389
  const overview = this.computeOverviewDisplayFields(instance, definition);
2326
2390
  const runtimeDetails = this.computeRuntimeDetails(instance, definition, activeBookmarks);
2327
2391
  const workflowVariablesTable = this.computeWorkflowVariablesTable(instance, definition);
2328
- const assignUserFields = await this.resolveAssignUserLookupFields(this.resolvePrimaryAssignUserId(instance, activeBookmarks));
2329
- await this.syncLinkedTaskAssignee(instance, assignUserFields);
2392
+ const assignUserFields = await this.resolveProjectionAssignUserFields(instance, activeBookmarks);
2393
+ if (!this.linkedTaskAssigneeAlreadyStamped(instance, assignUserFields)) {
2394
+ await this.syncLinkedTaskAssignee(instance, assignUserFields);
2395
+ }
2330
2396
  const scopeInfo = this.getSessionScopeInfo();
2331
2397
  const entityModel = {
2332
2398
  id: instance.id,
@@ -3422,6 +3488,7 @@ exports.BackendWorkflowEngineService = BackendWorkflowEngineService = BackendWor
3422
3488
  workflow_expression_scope_service_1.WorkflowExpressionScopeService,
3423
3489
  workflow_expression_evaluator_service_1.WorkflowExpressionEvaluatorService,
3424
3490
  workflow_request_session_adapter_1.WorkflowRequestSessionAdapter,
3425
- workflow_activity_registry_1.WorkflowActivityRegistryService])
3491
+ workflow_activity_registry_1.WorkflowActivityRegistryService,
3492
+ workflow_definition_runtime_cache_1.WorkflowDefinitionRuntimeCache])
3426
3493
  ], BackendWorkflowEngineService);
3427
3494
  //# sourceMappingURL=workflow-engine.service.js.map