@rytass/bpm-core-nestjs-module 0.21.0 → 0.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -0
- package/README.md +105 -1
- package/package.json +2 -2
- package/src/lib/attachment/attachment.service.js +2 -10
- package/src/lib/attachment/attachment.service.js.map +1 -1
- package/src/lib/attachment/file-upload-value-ids.d.ts +8 -0
- package/src/lib/attachment/file-upload-value-ids.js +15 -0
- package/src/lib/attachment/file-upload-value-ids.js.map +1 -0
- package/src/lib/bpm/bpm-root-options.d.ts +18 -0
- package/src/lib/bpm/bpm-root-options.js.map +1 -1
- package/src/lib/bpm/bpm-root.module.d.ts +11 -0
- package/src/lib/bpm/bpm-root.module.js +9 -4
- package/src/lib/bpm/bpm-root.module.js.map +1 -1
- package/src/lib/form-data-source/form-data-source.module.d.ts +8 -0
- package/src/lib/form-data-source/form-data-source.module.js +1 -1
- package/src/lib/form-data-source/form-data-source.module.js.map +1 -1
- package/src/lib/form-data-source/form-data-source.service.js +1 -1
- package/src/lib/form-data-source/form-data-source.service.js.map +1 -1
- package/src/lib/notification/notification.service.js +6 -0
- package/src/lib/notification/notification.service.js.map +1 -1
- package/src/lib/organization/organization-time-zone.d.ts +4 -2
- package/src/lib/organization/organization-time-zone.js +3 -6
- package/src/lib/organization/organization-time-zone.js.map +1 -1
- package/src/lib/template/template.service.js +51 -5
- package/src/lib/template/template.service.js.map +1 -1
- package/src/lib/template/workflow-definition.validator.js +84 -2
- package/src/lib/template/workflow-definition.validator.js.map +1 -1
- package/src/lib/workflow-engine/index.d.ts +1 -0
- package/src/lib/workflow-engine/index.js +1 -0
- package/src/lib/workflow-engine/index.js.map +1 -1
- package/src/lib/workflow-engine/initiator-custom-fields-resolver.token.d.ts +108 -0
- package/src/lib/workflow-engine/initiator-custom-fields-resolver.token.js +9 -0
- package/src/lib/workflow-engine/initiator-custom-fields-resolver.token.js.map +1 -0
- package/src/lib/workflow-engine/workflow-engine.enums.d.ts +1 -0
- package/src/lib/workflow-engine/workflow-engine.enums.js +1 -0
- package/src/lib/workflow-engine/workflow-engine.enums.js.map +1 -1
- package/src/lib/workflow-engine/workflow-engine.module.d.ts +2 -0
- package/src/lib/workflow-engine/workflow-engine.module.js +9 -3
- package/src/lib/workflow-engine/workflow-engine.module.js.map +1 -1
- package/src/lib/workflow-engine/workflow-engine.queries.d.ts +1 -1
- package/src/lib/workflow-engine/workflow-engine.queries.js +4 -3
- package/src/lib/workflow-engine/workflow-engine.queries.js.map +1 -1
- package/src/lib/workflow-engine/workflow-engine.service.d.ts +131 -14
- package/src/lib/workflow-engine/workflow-engine.service.js +654 -88
- package/src/lib/workflow-engine/workflow-engine.service.js.map +1 -1
|
@@ -29,6 +29,7 @@ import { TaskCandidateEntity } from './task-candidate.entity';
|
|
|
29
29
|
import { TaskEntity } from './task.entity';
|
|
30
30
|
import { ApprovalInstanceListViewEnum, ApprovalInstanceStateEnum, MemberTaskRoleEnum, TaskCandidateStatusEnum, TaskReassignmentErrorCodeEnum, TaskReassignmentOutcomeEnum } from './workflow-engine.enums';
|
|
31
31
|
import { WorkflowDryRunResultObject } from './workflow-dry-run.object';
|
|
32
|
+
import { BPMInitiatorCustomFieldsResolver } from './initiator-custom-fields-resolver.token';
|
|
32
33
|
import { BPMWorkflowServiceTaskDispatcher } from './workflow-service-task-dispatcher.token';
|
|
33
34
|
import { WorkflowTokenEntity } from './workflow-token.entity';
|
|
34
35
|
import { BPMRootRuntimeOptions } from '../bpm/bpm-root-options';
|
|
@@ -180,8 +181,9 @@ export declare class WorkflowEngineService {
|
|
|
180
181
|
private readonly logger;
|
|
181
182
|
private readonly approvalInstanceFieldFilterCompiler;
|
|
182
183
|
private readonly approvalInstanceFilterableFieldPolicy;
|
|
183
|
-
constructor(approvalInstanceRepository: Repository<ApprovalInstanceEntity>, workflowTokenRepository: Repository<WorkflowTokenEntity>, taskRepository: Repository<TaskEntity>, taskCandidateRepository: Repository<TaskCandidateEntity>, taskDecisionRepository: Repository<TaskDecisionEntity>, notificationRepository: Repository<NotificationEntity>, activityLogRepository: Repository<ActivityLogEntity>, adhocDirectiveRepository: Repository<AdhocDirectiveEntity>, approvalTemplateRepository: Repository<ApprovalTemplateEntity>, approvalTemplateVersionRepository: Repository<ApprovalTemplateVersionEntity>, formDefinitionVersionRepository: Repository<FormDefinitionVersionEntity>, attachmentService: AttachmentService, conditionService: ConditionService, delegationService: DelegationService, notificationService: NotificationService, signatureService: SignatureService, slaScheduleService: BPMSlaScheduleService, injectedServiceTaskDispatcher?: BPMWorkflowServiceTaskDispatcher, formDataSourceValueResolver?: BPMFormDataSourceValueResolver | undefined, rootOptions?: BPMRootRuntimeOptions, webhookDeliveryService?: WorkflowWebhookDeliveryService | undefined);
|
|
184
|
+
constructor(approvalInstanceRepository: Repository<ApprovalInstanceEntity>, workflowTokenRepository: Repository<WorkflowTokenEntity>, taskRepository: Repository<TaskEntity>, taskCandidateRepository: Repository<TaskCandidateEntity>, taskDecisionRepository: Repository<TaskDecisionEntity>, notificationRepository: Repository<NotificationEntity>, activityLogRepository: Repository<ActivityLogEntity>, adhocDirectiveRepository: Repository<AdhocDirectiveEntity>, approvalTemplateRepository: Repository<ApprovalTemplateEntity>, approvalTemplateVersionRepository: Repository<ApprovalTemplateVersionEntity>, formDefinitionVersionRepository: Repository<FormDefinitionVersionEntity>, attachmentService: AttachmentService, conditionService: ConditionService, delegationService: DelegationService, notificationService: NotificationService, signatureService: SignatureService, slaScheduleService: BPMSlaScheduleService, injectedServiceTaskDispatcher?: BPMWorkflowServiceTaskDispatcher, formDataSourceValueResolver?: BPMFormDataSourceValueResolver | undefined, rootOptions?: BPMRootRuntimeOptions, webhookDeliveryService?: WorkflowWebhookDeliveryService | undefined, injectedInitiatorCustomFieldsResolver?: BPMInitiatorCustomFieldsResolver);
|
|
184
185
|
private readonly serviceTaskDispatcher;
|
|
186
|
+
private readonly initiatorCustomFieldsResolver;
|
|
185
187
|
/** Webhooks each open engine transaction will send once it has committed. */
|
|
186
188
|
private readonly deferredWebhookDispatches;
|
|
187
189
|
private readonly organizationTimeZone;
|
|
@@ -362,7 +364,12 @@ export declare class WorkflowEngineService {
|
|
|
362
364
|
readonly totalInstanceCount: number;
|
|
363
365
|
}>;
|
|
364
366
|
private readDashboardOpenTasks;
|
|
365
|
-
|
|
367
|
+
/**
|
|
368
|
+
* The active templates `memberId` may start now. `authContext` is handed to
|
|
369
|
+
* the host's initiator `customFields` resolver; a host calling this without
|
|
370
|
+
* one gets a bare context for the member, as a submission does.
|
|
371
|
+
*/
|
|
372
|
+
listLaunchableApprovalTemplates(memberId: string, authContext?: BPMAuthContext): Promise<readonly ApprovalTemplateEntity[]>;
|
|
366
373
|
listWorkflowTokens(instanceId: string, scope?: WorkflowReadScope): Promise<readonly WorkflowTokenEntity[]>;
|
|
367
374
|
listTasks(instanceId: string, scope?: WorkflowReadScope): Promise<readonly TaskEntity[]>;
|
|
368
375
|
listInboxTasks(assigneeMemberId: string): Promise<readonly TaskEntity[]>;
|
|
@@ -394,6 +401,54 @@ export declare class WorkflowEngineService {
|
|
|
394
401
|
*/
|
|
395
402
|
private readTaskNodeSummaries;
|
|
396
403
|
private readDefaultInitiatorMetadataSnapshot;
|
|
404
|
+
/**
|
|
405
|
+
* The initiator snapshot the engine builds itself: what it knows of the
|
|
406
|
+
* initiator, with `customFields` filled by the host's resolver when there is
|
|
407
|
+
* one. Without a resolver this is exactly the default snapshot
|
|
408
|
+
* (`customFields` is `{}`). A submission (`submission` set) stores it and
|
|
409
|
+
* judges the initiator policy with it; the launchable template list
|
|
410
|
+
* (`submission: null`) only judges the policies with it, so both see the same
|
|
411
|
+
* `customFields` for the same member.
|
|
412
|
+
*
|
|
413
|
+
* Only `customFields` comes from the host. The other keys are the engine's
|
|
414
|
+
* and are written back after the resolver returns, so nothing it does can
|
|
415
|
+
* change who the initiator is. The resolver gets copies of the snapshot and
|
|
416
|
+
* of the form data for the same reason; `authContext` is the caller's own
|
|
417
|
+
* object, as every other host hook receives it.
|
|
418
|
+
*
|
|
419
|
+
* The two callers treat a resolver failure (an error, a bad value, the
|
|
420
|
+
* timeout) differently, on purpose:
|
|
421
|
+
*
|
|
422
|
+
* - A submission fails, and no case is created. Its snapshot is stored and
|
|
423
|
+
* routes the case from then on, so carrying on with `{}` would start a
|
|
424
|
+
* case on data the host never gave. It runs before the engine
|
|
425
|
+
* transaction, so a failure leaves nothing behind and a slow lookup holds
|
|
426
|
+
* no lock.
|
|
427
|
+
* - The list carries on with `customFields: {}` and logs a warning: one
|
|
428
|
+
* failing lookup must not take the whole list away. That fails closed: a
|
|
429
|
+
* policy that reads `initiator.customFields` then throws on the missing key
|
|
430
|
+
* and the list's per-template catch leaves that template out, while a
|
|
431
|
+
* template whose policy does not read it is listed as usual. Submitting is
|
|
432
|
+
* still judged against the resolver's real answer.
|
|
433
|
+
*/
|
|
434
|
+
private buildInitiatorMetadataSnapshot;
|
|
435
|
+
/**
|
|
436
|
+
* Calls the host's initiator `customFields` resolver within
|
|
437
|
+
* {@link INITIATOR_CUSTOM_FIELDS_RESOLVER_TIMEOUT_MS} and returns what it
|
|
438
|
+
* gave as the object the snapshot keeps.
|
|
439
|
+
*
|
|
440
|
+
* Every failure becomes an `InternalServerErrorException` with a message
|
|
441
|
+
* meant for the member, and the cause goes to the log only, so nothing of
|
|
442
|
+
* the host's lookup reaches the client: running out of time, an error that
|
|
443
|
+
* is not an `HttpException`, and a value that is not a plain JSON object. An
|
|
444
|
+
* `HttpException` the resolver throws is passed on as it is, because the
|
|
445
|
+
* host chose that answer for the member.
|
|
446
|
+
*
|
|
447
|
+
* A resolver that settles after the time has run out is not waited for; what
|
|
448
|
+
* it settles with is logged and dropped, so a late rejection is never left
|
|
449
|
+
* unhandled.
|
|
450
|
+
*/
|
|
451
|
+
private resolveInitiatorCustomFields;
|
|
397
452
|
listActivityLogs(instanceId: string, scope?: WorkflowReadScope): Promise<readonly ActivityLogEntity[]>;
|
|
398
453
|
private assertTaskReadable;
|
|
399
454
|
private isApprovalInstanceReadableByMember;
|
|
@@ -424,10 +479,11 @@ export declare class WorkflowEngineService {
|
|
|
424
479
|
* Re-resolves the delegation of a candidate whose turn has come. When the
|
|
425
480
|
* delegate already holds another candidate row on the task, the stored values
|
|
426
481
|
* are kept: (task_id, member_id) is unique, and that member signs from the
|
|
427
|
-
* row they already have. On a node that
|
|
428
|
-
*
|
|
429
|
-
*
|
|
430
|
-
*
|
|
482
|
+
* row they already have. On a node that keeps members out (the initiator and
|
|
483
|
+
* submitter, or the approvers of earlier stages) the stored values are kept
|
|
484
|
+
* as well when the new delegation path would run through one of them:
|
|
485
|
+
* creation already filtered such paths out, and a delegation added while the
|
|
486
|
+
* candidate waited must not bring them back.
|
|
431
487
|
*/
|
|
432
488
|
private resolveActivationDelegation;
|
|
433
489
|
private markTaskCandidateDecision;
|
|
@@ -530,12 +586,52 @@ export declare class WorkflowEngineService {
|
|
|
530
586
|
*/
|
|
531
587
|
private notifySeatReplaced;
|
|
532
588
|
/**
|
|
533
|
-
* Resolves who gets the node's task.
|
|
534
|
-
* skipped (`excludeInitiator.whenEmpty
|
|
535
|
-
*
|
|
536
|
-
* token instead.
|
|
589
|
+
* Resolves who gets the node's task. A {@link SkippedRuntimeTask} means the
|
|
590
|
+
* node asked to be skipped (`excludeInitiator.whenEmpty` or
|
|
591
|
+
* `excludeNodeActors.whenEmpty` = SKIP_NODE) because everyone left was kept
|
|
592
|
+
* out: the sole caller creates no task and advances the token instead.
|
|
593
|
+
*
|
|
594
|
+
* With both exclusions set the initiator rule runs first. When it alone
|
|
595
|
+
* leaves nobody, `excludeInitiator.whenEmpty` decides; when it leaves
|
|
596
|
+
* somebody and the earlier-stage rule then removes them all,
|
|
597
|
+
* `excludeNodeActors.whenEmpty` decides.
|
|
537
598
|
*/
|
|
538
599
|
private resolveRuntimeTaskCandidates;
|
|
600
|
+
/**
|
|
601
|
+
* Everyone `node` keeps out of its approvers, per rule: the initiator and
|
|
602
|
+
* the submitter for `excludeInitiator`, and everyone who actually approved
|
|
603
|
+
* one of the listed earlier stages for `excludeNodeActors`. Read through
|
|
604
|
+
* `manager` so an approval written earlier in this transaction counts.
|
|
605
|
+
*/
|
|
606
|
+
private readNodeExclusions;
|
|
607
|
+
/**
|
|
608
|
+
* The people who approved any of `nodeIds`, each listed node read on its own
|
|
609
|
+
* with the `NODE_ACTOR` rules ({@link readNodeActorMemberIds}) and the
|
|
610
|
+
* results combined. A source reads only the most recent of its listed nodes;
|
|
611
|
+
* an exclusion must cover every listed node, so it asks one node at a time.
|
|
612
|
+
*
|
|
613
|
+
* There is no round boundary here: a node's newest batch is what counts. The
|
|
614
|
+
* publish lint makes that the right batch, since every listed node runs and
|
|
615
|
+
* is signed by a person on every path to this node (a return to the start
|
|
616
|
+
* runs it again; a return to a stage below it leaves its earlier approval
|
|
617
|
+
* standing, and the exclusion with it).
|
|
618
|
+
*/
|
|
619
|
+
private readExcludedNodeActorMemberIds;
|
|
620
|
+
/**
|
|
621
|
+
* Whether `targetMemberId` may not take a seat on `node` under
|
|
622
|
+
* `excludeNodeActors`, checked the way task creation checks a candidate: the
|
|
623
|
+
* target is one of the excluded members, or one end of a delegation between
|
|
624
|
+
* the target and an excluded member is on the path. A delegation is read in
|
|
625
|
+
* both directions, since the target may be the delegate of an excluded
|
|
626
|
+
* member, or delegate an excluded member's seat onward.
|
|
627
|
+
*/
|
|
628
|
+
private isExcludedNodeActorTarget;
|
|
629
|
+
/**
|
|
630
|
+
* The principals the approvals stand for: a delegate who approved counts as
|
|
631
|
+
* the member who delegated to them, read from the candidate row each approval
|
|
632
|
+
* was signed on (see {@link readRuleDelegatorMemberIds}).
|
|
633
|
+
*/
|
|
634
|
+
private readApprovalPrincipalMemberIds;
|
|
539
635
|
private resolveInitiatorManagerReplacements;
|
|
540
636
|
private buildDelegationContext;
|
|
541
637
|
private delegateResolvedCandidates;
|
|
@@ -600,6 +696,12 @@ export declare class WorkflowEngineService {
|
|
|
600
696
|
* tasks and approvals the SLA timeout made do not count.
|
|
601
697
|
*/
|
|
602
698
|
private readNodeActorMemberIds;
|
|
699
|
+
/**
|
|
700
|
+
* The real approvals (earliest first) of the most recent batch among
|
|
701
|
+
* `nodeIds`: the rows {@link readNodeActorMemberIds} reads the approvers from.
|
|
702
|
+
* Kept as decisions so the exclusion can also reach each decision's task.
|
|
703
|
+
*/
|
|
704
|
+
private readNodeActorApprovals;
|
|
603
705
|
private resolvePositionCandidates;
|
|
604
706
|
/**
|
|
605
707
|
* The members who hold the position today (organisation time zone) within
|
|
@@ -609,12 +711,27 @@ export declare class WorkflowEngineService {
|
|
|
609
711
|
private readActivePositionMemberIds;
|
|
610
712
|
private resolveInitiatorManagerCandidates;
|
|
611
713
|
/**
|
|
612
|
-
* Walks up
|
|
613
|
-
*
|
|
614
|
-
*
|
|
615
|
-
*
|
|
714
|
+
* Walks up a manager chain, nearest manager first, until a manager whose
|
|
715
|
+
* position level reaches `minPositionLevel` is added. The chain starts at
|
|
716
|
+
* the initiator unless `startFrom` names someone else, and the start person
|
|
717
|
+
* is never on it: the walk begins at their direct manager. The list is
|
|
718
|
+
* returned nearest manager first. Members in `skippedMemberIds` are walked
|
|
719
|
+
* past without joining the chain or counting as the stopping point, and so
|
|
720
|
+
* are managers below `startPositionLevel`, until the first one at or above
|
|
721
|
+
* it starts the chain.
|
|
616
722
|
*/
|
|
617
723
|
private resolveOrgManagerChainCandidates;
|
|
724
|
+
/**
|
|
725
|
+
* Whose manager an `ORG_MANAGER_CHAIN` starts from. `memberId` is `null`
|
|
726
|
+
* when the start names nobody (an empty form field, an earlier stage nobody
|
|
727
|
+
* approved), with `missingReason` saying why; `description` is the lead-in
|
|
728
|
+
* of the "no manager reaches the level" reason, empty for the initiator so
|
|
729
|
+
* a chain without a start keeps today's wording.
|
|
730
|
+
*
|
|
731
|
+
* A start that picks more than one person is refused rather than guessed,
|
|
732
|
+
* the same as a manager rule that names several managers at one priority.
|
|
733
|
+
*/
|
|
734
|
+
private resolveOrgManagerChainStart;
|
|
618
735
|
/** Highest position level over the member's active memberships, or `null`. */
|
|
619
736
|
private readMemberPositionLevel;
|
|
620
737
|
/**
|