@rytass/bpm-core-nestjs-module 0.22.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +95 -0
- package/README.md +68 -1
- package/package.json +2 -2
- package/src/index.d.ts +1 -0
- package/src/index.js +1 -0
- package/src/index.js.map +1 -1
- package/src/lib/bpm/bpm-root-options.d.ts +57 -0
- package/src/lib/bpm/bpm-root-options.js.map +1 -1
- package/src/lib/bpm/bpm-root.module.d.ts +21 -0
- package/src/lib/bpm/bpm-root.module.js +6 -0
- package/src/lib/bpm/bpm-root.module.js.map +1 -1
- package/src/lib/form/dto/form-definition.input.d.ts +5 -0
- package/src/lib/form/dto/form-definition.input.js.map +1 -1
- package/src/lib/form/form-definition.entity.d.ts +5 -0
- package/src/lib/form/form-definition.entity.js +7 -0
- package/src/lib/form/form-definition.entity.js.map +1 -1
- package/src/lib/form/form-schema.validator.js +17 -5
- package/src/lib/form/form-schema.validator.js.map +1 -1
- package/src/lib/form/form.queries.d.ts +2 -2
- package/src/lib/form/form.queries.js +17 -5
- package/src/lib/form/form.queries.js.map +1 -1
- package/src/lib/form/form.service.d.ts +2 -1
- package/src/lib/form/form.service.js +10 -5
- package/src/lib/form/form.service.js.map +1 -1
- package/src/lib/form-data-source/form-data-source-value-resolver.service.js +22 -2
- package/src/lib/form-data-source/form-data-source-value-resolver.service.js.map +1 -1
- package/src/lib/form-data-source/form-data-source.errors.d.ts +11 -0
- package/src/lib/form-data-source/form-data-source.errors.js +14 -1
- package/src/lib/form-data-source/form-data-source.errors.js.map +1 -1
- package/src/lib/form-data-source/form-data-source.service.d.ts +6 -0
- package/src/lib/form-data-source/form-data-source.service.js +37 -3
- package/src/lib/form-data-source/form-data-source.service.js.map +1 -1
- package/src/lib/instance-event/approval-instance-event.entity.d.ts +27 -0
- package/src/lib/instance-event/approval-instance-event.entity.js +93 -0
- package/src/lib/instance-event/approval-instance-event.entity.js.map +1 -0
- package/src/lib/instance-event/index.d.ts +13 -0
- package/src/lib/instance-event/index.js +17 -0
- package/src/lib/instance-event/index.js.map +1 -0
- package/src/lib/instance-event/instance-event.delivery-scheduler.service.d.ts +21 -0
- package/src/lib/instance-event/instance-event.delivery-scheduler.service.js +81 -0
- package/src/lib/instance-event/instance-event.delivery-scheduler.service.js.map +1 -0
- package/src/lib/instance-event/instance-event.delivery.service.d.ts +69 -0
- package/src/lib/instance-event/instance-event.delivery.service.js +259 -0
- package/src/lib/instance-event/instance-event.delivery.service.js.map +1 -0
- package/src/lib/instance-event/instance-event.delivery.subscriber.d.ts +24 -0
- package/src/lib/instance-event/instance-event.delivery.subscriber.js +85 -0
- package/src/lib/instance-event/instance-event.delivery.subscriber.js.map +1 -0
- package/src/lib/instance-event/instance-event.enums.d.ts +12 -0
- package/src/lib/instance-event/instance-event.enums.js +28 -0
- package/src/lib/instance-event/instance-event.enums.js.map +1 -0
- package/src/lib/instance-event/instance-event.module.d.ts +13 -0
- package/src/lib/instance-event/instance-event.module.js +52 -0
- package/src/lib/instance-event/instance-event.module.js.map +1 -0
- package/src/lib/instance-event/instance-event.object.d.ts +24 -0
- package/src/lib/instance-event/instance-event.object.js +73 -0
- package/src/lib/instance-event/instance-event.object.js.map +1 -0
- package/src/lib/instance-event/instance-event.options.d.ts +26 -0
- package/src/lib/instance-event/instance-event.options.js +35 -0
- package/src/lib/instance-event/instance-event.options.js.map +1 -0
- package/src/lib/instance-event/instance-event.resolver.d.ts +10 -0
- package/src/lib/instance-event/instance-event.resolver.js +75 -0
- package/src/lib/instance-event/instance-event.resolver.js.map +1 -0
- package/src/lib/instance-event/instance-event.service.d.ts +18 -0
- package/src/lib/instance-event/instance-event.service.js +37 -0
- package/src/lib/instance-event/instance-event.service.js.map +1 -0
- package/src/lib/instance-event/instance-event.token.d.ts +19 -0
- package/src/lib/instance-event/instance-event.token.js +9 -0
- package/src/lib/instance-event/instance-event.token.js.map +1 -0
- package/src/lib/instance-event/instance-event.types.d.ts +67 -0
- package/src/lib/instance-event/instance-event.types.js +9 -0
- package/src/lib/instance-event/instance-event.types.js.map +1 -0
- package/src/lib/instance-event/instance-event.writer.d.ts +21 -0
- package/src/lib/instance-event/instance-event.writer.js +45 -0
- package/src/lib/instance-event/instance-event.writer.js.map +1 -0
- package/src/lib/migrations/0000000032000-host-integration-round.d.ts +25 -0
- package/src/lib/migrations/0000000032000-host-integration-round.js +104 -0
- package/src/lib/migrations/0000000032000-host-integration-round.js.map +1 -0
- package/src/lib/migrations/0000000033000-activity-log-advance-failed-index.d.ts +35 -0
- package/src/lib/migrations/0000000033000-activity-log-advance-failed-index.js +51 -0
- package/src/lib/migrations/0000000033000-activity-log-advance-failed-index.js.map +1 -0
- package/src/lib/migrations/index.d.ts +2 -0
- package/src/lib/migrations/index.js +6 -0
- package/src/lib/migrations/index.js.map +1 -1
- package/src/lib/notification/notification.service.d.ts +3 -2
- package/src/lib/notification/notification.service.js +52 -10
- package/src/lib/notification/notification.service.js.map +1 -1
- package/src/lib/template/approval-template-version.entity.d.ts +9 -1
- package/src/lib/template/approval-template-version.entity.js +11 -1
- package/src/lib/template/approval-template-version.entity.js.map +1 -1
- package/src/lib/template/approval-template.entity.d.ts +18 -0
- package/src/lib/template/approval-template.entity.js +23 -0
- package/src/lib/template/approval-template.entity.js.map +1 -1
- package/src/lib/template/dto/approval-template.input.d.ts +21 -0
- package/src/lib/template/dto/approval-template.input.js +38 -0
- package/src/lib/template/dto/approval-template.input.js.map +1 -1
- package/src/lib/template/dto/compose-approval-template.input.d.ts +23 -0
- package/src/lib/template/dto/compose-approval-template.input.js +37 -0
- package/src/lib/template/dto/compose-approval-template.input.js.map +1 -1
- package/src/lib/template/template-key.d.ts +26 -0
- package/src/lib/template/template-key.js +67 -0
- package/src/lib/template/template-key.js.map +1 -0
- package/src/lib/template/template.enums.d.ts +11 -0
- package/src/lib/template/template.enums.js +17 -1
- package/src/lib/template/template.enums.js.map +1 -1
- package/src/lib/template/template.queries.d.ts +3 -2
- package/src/lib/template/template.queries.js +29 -4
- package/src/lib/template/template.queries.js.map +1 -1
- package/src/lib/template/template.service.d.ts +8 -1
- package/src/lib/template/template.service.js +111 -17
- package/src/lib/template/template.service.js.map +1 -1
- package/src/lib/template/workflow-definition.validator.js +12 -6
- package/src/lib/template/workflow-definition.validator.js.map +1 -1
- package/src/lib/workflow-engine/approver-filled-table-columns.d.ts +91 -0
- package/src/lib/workflow-engine/approver-filled-table-columns.js +301 -0
- package/src/lib/workflow-engine/approver-filled-table-columns.js.map +1 -0
- package/src/lib/workflow-engine/dto/admin-cancel-approval-instance.input.d.ts +9 -0
- package/src/lib/workflow-engine/dto/admin-cancel-approval-instance.input.js +24 -0
- package/src/lib/workflow-engine/dto/admin-cancel-approval-instance.input.js.map +1 -0
- package/src/lib/workflow-engine/dto/dry-run-approval-workflow.input.d.ts +7 -0
- package/src/lib/workflow-engine/dto/dry-run-approval-workflow.input.js +9 -0
- package/src/lib/workflow-engine/dto/dry-run-approval-workflow.input.js.map +1 -1
- package/src/lib/workflow-engine/dto/reassign-member-tasks.input.d.ts +2 -0
- package/src/lib/workflow-engine/dto/reassign-member-tasks.input.js +8 -0
- package/src/lib/workflow-engine/dto/reassign-member-tasks.input.js.map +1 -1
- package/src/lib/workflow-engine/index.d.ts +3 -0
- package/src/lib/workflow-engine/index.js +3 -0
- package/src/lib/workflow-engine/index.js.map +1 -1
- package/src/lib/workflow-engine/instance-advance-failure.d.ts +28 -0
- package/src/lib/workflow-engine/instance-advance-failure.js +20 -0
- package/src/lib/workflow-engine/instance-advance-failure.js.map +1 -0
- package/src/lib/workflow-engine/instance-guard.runner.d.ts +19 -0
- package/src/lib/workflow-engine/instance-guard.runner.js +102 -0
- package/src/lib/workflow-engine/instance-guard.runner.js.map +1 -0
- package/src/lib/workflow-engine/instance-guard.token.d.ts +101 -0
- package/src/lib/workflow-engine/instance-guard.token.js +9 -0
- package/src/lib/workflow-engine/instance-guard.token.js.map +1 -0
- package/src/lib/workflow-engine/missing-form-fields.d.ts +12 -0
- package/src/lib/workflow-engine/missing-form-fields.js +27 -0
- package/src/lib/workflow-engine/missing-form-fields.js.map +1 -0
- package/src/lib/workflow-engine/stuck-approval-instance.object.d.ts +22 -0
- package/src/lib/workflow-engine/stuck-approval-instance.object.js +107 -0
- package/src/lib/workflow-engine/stuck-approval-instance.object.js.map +1 -0
- package/src/lib/workflow-engine/stuck-approval-instance.query.d.ts +22 -0
- package/src/lib/workflow-engine/stuck-approval-instance.query.js +139 -0
- package/src/lib/workflow-engine/stuck-approval-instance.query.js.map +1 -0
- package/src/lib/workflow-engine/workflow-engine.enums.d.ts +11 -0
- package/src/lib/workflow-engine/workflow-engine.enums.js +16 -1
- 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 +3 -0
- package/src/lib/workflow-engine/workflow-engine.module.js.map +1 -1
- package/src/lib/workflow-engine/workflow-engine.mutations.d.ts +3 -1
- package/src/lib/workflow-engine/workflow-engine.mutations.js +39 -6
- package/src/lib/workflow-engine/workflow-engine.mutations.js.map +1 -1
- package/src/lib/workflow-engine/workflow-engine.queries.d.ts +10 -8
- package/src/lib/workflow-engine/workflow-engine.queries.js +131 -28
- package/src/lib/workflow-engine/workflow-engine.queries.js.map +1 -1
- package/src/lib/workflow-engine/workflow-engine.service.d.ts +348 -10
- package/src/lib/workflow-engine/workflow-engine.service.js +1396 -118
- package/src/lib/workflow-engine/workflow-engine.service.js.map +1 -1
- package/src/lib/workflow-engine/workflow-engine.tokens.d.ts +5 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reassign-member-tasks.input.js","sourceRoot":"","sources":["../../../../../../../libs/bpm-core/src/lib/workflow-engine/dto/reassign-member-tasks.input.ts"],"names":[],"mappings":";;;;AAAA,
|
|
1
|
+
{"version":3,"file":"reassign-member-tasks.input.js","sourceRoot":"","sources":["../../../../../../../libs/bpm-core/src/lib/workflow-engine/dto/reassign-member-tasks.input.ts"],"names":[],"mappings":";;;;AAAA,6CAAuD;AACvD,qDAOyB;AAGlB,IAAM,wBAAwB,GAA9B,MAAM,wBAAwB;CA0BpC,CAAA;AA1BY,4DAAwB;AAGnC;IAFC,IAAA,eAAK,GAAE;IACP,IAAA,0BAAQ,GAAE;;8DACW;AAItB;IAFC,IAAA,eAAK,GAAE;IACP,IAAA,0BAAQ,GAAE;;4DACS;AAIpB;IAFC,IAAA,eAAK,GAAE;IACP,IAAA,0BAAQ,GAAE;;wDACK;AAMhB;IAHC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACxC,IAAA,4BAAU,GAAE;IACZ,IAAA,2BAAS,GAAE;;wDACY;AAQxB;IALC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,CAAC,YAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACrC,IAAA,4BAAU,GAAE;IACZ,IAAA,yBAAO,GAAE;IACT,IAAA,+BAAa,GAAE;IACf,IAAA,wBAAM,EAAC,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;;yDACJ;mCAzBf,wBAAwB;IADpC,IAAA,mBAAS,GAAE;GACC,wBAAwB,CA0BpC"}
|
|
@@ -5,6 +5,7 @@ export * from './approval-instance-page-info.object';
|
|
|
5
5
|
export * from './approval-instance.entity';
|
|
6
6
|
export * from './dto/adhoc-notification.input';
|
|
7
7
|
export * from './dto/adhoc-target.input';
|
|
8
|
+
export * from './dto/admin-cancel-approval-instance.input';
|
|
8
9
|
export * from './dto/cancel-approval-instance.input';
|
|
9
10
|
export * from './dto/decide-task.input';
|
|
10
11
|
export * from './dto/dry-run-approval-workflow.input';
|
|
@@ -13,9 +14,11 @@ export * from './dto/reassign-task.input';
|
|
|
13
14
|
export * from './dto/resubmit-approval-instance.input';
|
|
14
15
|
export * from './dto/submit-approval-instance.input';
|
|
15
16
|
export * from './initiator-custom-fields-resolver.token';
|
|
17
|
+
export * from './instance-guard.token';
|
|
16
18
|
export * from './task-candidate.entity';
|
|
17
19
|
export * from './task-decision.entity';
|
|
18
20
|
export * from './task.entity';
|
|
21
|
+
export * from './stuck-approval-instance.object';
|
|
19
22
|
export * from './task-reassignment.object';
|
|
20
23
|
export * from './workflow-condition-evaluator';
|
|
21
24
|
export * from './workflow-dry-run.object';
|
|
@@ -8,6 +8,7 @@ tslib_1.__exportStar(require("./approval-instance-page-info.object"), exports);
|
|
|
8
8
|
tslib_1.__exportStar(require("./approval-instance.entity"), exports);
|
|
9
9
|
tslib_1.__exportStar(require("./dto/adhoc-notification.input"), exports);
|
|
10
10
|
tslib_1.__exportStar(require("./dto/adhoc-target.input"), exports);
|
|
11
|
+
tslib_1.__exportStar(require("./dto/admin-cancel-approval-instance.input"), exports);
|
|
11
12
|
tslib_1.__exportStar(require("./dto/cancel-approval-instance.input"), exports);
|
|
12
13
|
tslib_1.__exportStar(require("./dto/decide-task.input"), exports);
|
|
13
14
|
tslib_1.__exportStar(require("./dto/dry-run-approval-workflow.input"), exports);
|
|
@@ -16,9 +17,11 @@ tslib_1.__exportStar(require("./dto/reassign-task.input"), exports);
|
|
|
16
17
|
tslib_1.__exportStar(require("./dto/resubmit-approval-instance.input"), exports);
|
|
17
18
|
tslib_1.__exportStar(require("./dto/submit-approval-instance.input"), exports);
|
|
18
19
|
tslib_1.__exportStar(require("./initiator-custom-fields-resolver.token"), exports);
|
|
20
|
+
tslib_1.__exportStar(require("./instance-guard.token"), exports);
|
|
19
21
|
tslib_1.__exportStar(require("./task-candidate.entity"), exports);
|
|
20
22
|
tslib_1.__exportStar(require("./task-decision.entity"), exports);
|
|
21
23
|
tslib_1.__exportStar(require("./task.entity"), exports);
|
|
24
|
+
tslib_1.__exportStar(require("./stuck-approval-instance.object"), exports);
|
|
22
25
|
tslib_1.__exportStar(require("./task-reassignment.object"), exports);
|
|
23
26
|
tslib_1.__exportStar(require("./workflow-condition-evaluator"), exports);
|
|
24
27
|
tslib_1.__exportStar(require("./workflow-dry-run.object"), exports);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/workflow-engine/index.ts"],"names":[],"mappings":";;;AAAA,gEAAsC;AACtC,mEAAyC;AACzC,wDAA8B;AAC9B,+EAAqD;AACrD,qEAA2C;AAC3C,yEAA+C;AAC/C,mEAAyC;AACzC,+EAAqD;AACrD,kEAAwC;AACxC,gFAAsD;AACtD,4EAAkD;AAClD,oEAA0C;AAC1C,iFAAuD;AACvD,+EAAqD;AACrD,mFAAyD;AACzD,kEAAwC;AACxC,iEAAuC;AACvC,wDAA8B;AAC9B,qEAA2C;AAC3C,yEAA+C;AAC/C,oEAA0C;AAC1C,8EAAoD;AACpD,kEAAwC;AACxC,mEAAyC;AACzC,oEAA0C;AAC1C,mEAAyC;AACzC,mFAAyD;AACzD,kEAAwC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/workflow-engine/index.ts"],"names":[],"mappings":";;;AAAA,gEAAsC;AACtC,mEAAyC;AACzC,wDAA8B;AAC9B,+EAAqD;AACrD,qEAA2C;AAC3C,yEAA+C;AAC/C,mEAAyC;AACzC,qFAA2D;AAC3D,+EAAqD;AACrD,kEAAwC;AACxC,gFAAsD;AACtD,4EAAkD;AAClD,oEAA0C;AAC1C,iFAAuD;AACvD,+EAAqD;AACrD,mFAAyD;AACzD,iEAAuC;AACvC,kEAAwC;AACxC,iEAAuC;AACvC,wDAA8B;AAC9B,2EAAiD;AACjD,qEAA2C;AAC3C,yEAA+C;AAC/C,oEAA0C;AAC1C,8EAAoD;AACpD,kEAAwC;AACxC,mEAAyC;AACzC,oEAA0C;AAC1C,mEAAyC;AACzC,mFAAyD;AACzD,kEAAwC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { HttpException } from '@nestjs/common';
|
|
2
|
+
/** Which public operation tried to move the instance on. */
|
|
3
|
+
export type InstanceAdvanceFailureKind = 'DECISION' | 'RESUBMIT';
|
|
4
|
+
/** What the `ADVANCE_FAILED` activity row says about the attempt. */
|
|
5
|
+
export interface InstanceAdvanceFailureContext {
|
|
6
|
+
readonly action: 'APPROVED' | 'RETURNED' | null;
|
|
7
|
+
/** The person who acted; for an SLA timeout, the member it acted as. */
|
|
8
|
+
readonly actorMemberId: string;
|
|
9
|
+
readonly automatic: 'SLA_AUTO_APPROVE' | null;
|
|
10
|
+
readonly instanceId: string;
|
|
11
|
+
readonly kind: InstanceAdvanceFailureKind;
|
|
12
|
+
/** The node the decision was made on; `null` for a resubmission. */
|
|
13
|
+
readonly nodeId: string | null;
|
|
14
|
+
/** The decided task; `null` for a resubmission. */
|
|
15
|
+
readonly taskId: string | null;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Carries a failed attempt to move an instance on from the call site that saw
|
|
19
|
+
* it, through the rolled-back transaction, to the public method that records
|
|
20
|
+
* it. It exists only for that trip: the public method records it and throws
|
|
21
|
+
* {@link InstanceAdvanceFailure.originalError} instead, so no caller ever sees
|
|
22
|
+
* this class. Deliberately not exported from the library index.
|
|
23
|
+
*/
|
|
24
|
+
export declare class InstanceAdvanceFailure extends Error {
|
|
25
|
+
readonly context: InstanceAdvanceFailureContext;
|
|
26
|
+
readonly originalError: HttpException;
|
|
27
|
+
constructor(originalError: HttpException, context: InstanceAdvanceFailureContext);
|
|
28
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InstanceAdvanceFailure = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Carries a failed attempt to move an instance on from the call site that saw
|
|
6
|
+
* it, through the rolled-back transaction, to the public method that records
|
|
7
|
+
* it. It exists only for that trip: the public method records it and throws
|
|
8
|
+
* {@link InstanceAdvanceFailure.originalError} instead, so no caller ever sees
|
|
9
|
+
* this class. Deliberately not exported from the library index.
|
|
10
|
+
*/
|
|
11
|
+
class InstanceAdvanceFailure extends Error {
|
|
12
|
+
constructor(originalError, context) {
|
|
13
|
+
super(originalError.message);
|
|
14
|
+
this.name = 'InstanceAdvanceFailure';
|
|
15
|
+
this.context = context;
|
|
16
|
+
this.originalError = originalError;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.InstanceAdvanceFailure = InstanceAdvanceFailure;
|
|
20
|
+
//# sourceMappingURL=instance-advance-failure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-advance-failure.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/workflow-engine/instance-advance-failure.ts"],"names":[],"mappings":";;;AAmBA;;;;;;GAMG;AACH,MAAa,sBAAuB,SAAQ,KAAK;IAK/C,YACE,aAA4B,EAC5B,OAAsC;QAEtC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAE7B,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;IACrC,CAAC;CACF;AAfD,wDAeC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { BPMInstanceGuard, BPMInstanceGuardInput } from './instance-guard.token';
|
|
2
|
+
/** Default for `instanceGuardTimeoutMs` (ADR 27 §2.2). */
|
|
3
|
+
export declare const BPM_INSTANCE_GUARD_DEFAULT_TIMEOUT_MS = 5000;
|
|
4
|
+
export declare const BPM_INSTANCE_GUARD_TIMEOUT_CODE = "BPM_INSTANCE_GUARD_TIMEOUT";
|
|
5
|
+
export declare const BPM_INSTANCE_GUARD_FAILED_CODE = "BPM_INSTANCE_GUARD_FAILED";
|
|
6
|
+
export declare function isInstanceGuardError(error: unknown): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Runs the host guard for one engine path and throws if the path must stop.
|
|
9
|
+
*
|
|
10
|
+
* Returns normally only when the guard answered with an empty list in time.
|
|
11
|
+
* Call it inside the engine transaction, after the case lock is taken, so a
|
|
12
|
+
* throw rolls the whole change back.
|
|
13
|
+
*
|
|
14
|
+
* - non-empty issues: 400 `createFormDataBadRequest`
|
|
15
|
+
* - no answer within `timeoutMs`: 503 `BPM_INSTANCE_GUARD_TIMEOUT` (fail closed)
|
|
16
|
+
* - a thrown `HttpException`: rethrown unchanged
|
|
17
|
+
* - any other error, or a malformed answer: 503 `BPM_INSTANCE_GUARD_FAILED`
|
|
18
|
+
*/
|
|
19
|
+
export declare function runInstanceGuard(guard: BPMInstanceGuard, input: BPMInstanceGuardInput, timeoutMs: number): Promise<void>;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BPM_INSTANCE_GUARD_FAILED_CODE = exports.BPM_INSTANCE_GUARD_TIMEOUT_CODE = exports.BPM_INSTANCE_GUARD_DEFAULT_TIMEOUT_MS = void 0;
|
|
4
|
+
exports.isInstanceGuardError = isInstanceGuardError;
|
|
5
|
+
exports.runInstanceGuard = runInstanceGuard;
|
|
6
|
+
const common_1 = require("@nestjs/common");
|
|
7
|
+
const form_data_issue_1 = require("../form/form-data-issue");
|
|
8
|
+
/** Default for `instanceGuardTimeoutMs` (ADR 27 §2.2). */
|
|
9
|
+
exports.BPM_INSTANCE_GUARD_DEFAULT_TIMEOUT_MS = 5000;
|
|
10
|
+
exports.BPM_INSTANCE_GUARD_TIMEOUT_CODE = 'BPM_INSTANCE_GUARD_TIMEOUT';
|
|
11
|
+
exports.BPM_INSTANCE_GUARD_FAILED_CODE = 'BPM_INSTANCE_GUARD_FAILED';
|
|
12
|
+
/**
|
|
13
|
+
* Every error the guard path raises: the 400 for refused issues, the 503 for a
|
|
14
|
+
* timeout or a failing guard, and an `HttpException` the host threw itself.
|
|
15
|
+
* Lets a caller tell a guard refusal apart from any other failure without
|
|
16
|
+
* matching on messages.
|
|
17
|
+
*/
|
|
18
|
+
const instanceGuardErrors = new WeakSet();
|
|
19
|
+
function markInstanceGuardError(error) {
|
|
20
|
+
instanceGuardErrors.add(error);
|
|
21
|
+
return error;
|
|
22
|
+
}
|
|
23
|
+
function isInstanceGuardError(error) {
|
|
24
|
+
return typeof error === 'object' && error !== null
|
|
25
|
+
? instanceGuardErrors.has(error)
|
|
26
|
+
: false;
|
|
27
|
+
}
|
|
28
|
+
function createGuardUnavailable(code, message) {
|
|
29
|
+
return markInstanceGuardError(new common_1.ServiceUnavailableException({
|
|
30
|
+
code,
|
|
31
|
+
error: 'Service Unavailable',
|
|
32
|
+
message,
|
|
33
|
+
statusCode: 503,
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
36
|
+
function isGuardIssue(value) {
|
|
37
|
+
if (typeof value !== 'object' || value === null) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
const issue = value;
|
|
41
|
+
return (typeof issue.message === 'string' &&
|
|
42
|
+
typeof issue.path === 'string' &&
|
|
43
|
+
issue.reason === 'HOST_RULE' &&
|
|
44
|
+
(issue.code === undefined || typeof issue.code === 'string'));
|
|
45
|
+
}
|
|
46
|
+
function readIssueFormDataErrors(issues) {
|
|
47
|
+
return issues.map((issue) => ({
|
|
48
|
+
message: issue.message,
|
|
49
|
+
path: issue.path,
|
|
50
|
+
reason: issue.reason,
|
|
51
|
+
...(issue.code === undefined ? {} : { code: issue.code }),
|
|
52
|
+
}));
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Runs the host guard for one engine path and throws if the path must stop.
|
|
56
|
+
*
|
|
57
|
+
* Returns normally only when the guard answered with an empty list in time.
|
|
58
|
+
* Call it inside the engine transaction, after the case lock is taken, so a
|
|
59
|
+
* throw rolls the whole change back.
|
|
60
|
+
*
|
|
61
|
+
* - non-empty issues: 400 `createFormDataBadRequest`
|
|
62
|
+
* - no answer within `timeoutMs`: 503 `BPM_INSTANCE_GUARD_TIMEOUT` (fail closed)
|
|
63
|
+
* - a thrown `HttpException`: rethrown unchanged
|
|
64
|
+
* - any other error, or a malformed answer: 503 `BPM_INSTANCE_GUARD_FAILED`
|
|
65
|
+
*/
|
|
66
|
+
async function runInstanceGuard(guard, input, timeoutMs) {
|
|
67
|
+
const timeoutError = markInstanceGuardError(new Error(`BPM_INSTANCE_GUARD_TIMEOUT_${timeoutMs}MS`));
|
|
68
|
+
let timer;
|
|
69
|
+
let issues;
|
|
70
|
+
try {
|
|
71
|
+
issues = await Promise.race([
|
|
72
|
+
Promise.resolve().then(() => guard.check(input)),
|
|
73
|
+
new Promise((_resolve, reject) => {
|
|
74
|
+
timer = setTimeout(() => {
|
|
75
|
+
reject(timeoutError);
|
|
76
|
+
}, timeoutMs);
|
|
77
|
+
}),
|
|
78
|
+
]);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
if (error === timeoutError) {
|
|
82
|
+
throw createGuardUnavailable(exports.BPM_INSTANCE_GUARD_TIMEOUT_CODE, `Instance guard did not answer within ${timeoutMs} ms`);
|
|
83
|
+
}
|
|
84
|
+
if (error instanceof common_1.HttpException) {
|
|
85
|
+
markInstanceGuardError(error);
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
throw createGuardUnavailable(exports.BPM_INSTANCE_GUARD_FAILED_CODE, 'Instance guard failed');
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
clearTimeout(timer);
|
|
92
|
+
}
|
|
93
|
+
if (!Array.isArray(issues) || !issues.every(isGuardIssue)) {
|
|
94
|
+
throw createGuardUnavailable(exports.BPM_INSTANCE_GUARD_FAILED_CODE, 'Instance guard returned an answer of the wrong shape');
|
|
95
|
+
}
|
|
96
|
+
if (issues.length === 0) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const formDataErrors = readIssueFormDataErrors(issues);
|
|
100
|
+
throw markInstanceGuardError((0, form_data_issue_1.createFormDataBadRequest)((0, form_data_issue_1.readFormDataIssueMessage)(formDataErrors), formDataErrors));
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=instance-guard.runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-guard.runner.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/workflow-engine/instance-guard.runner.ts"],"names":[],"mappings":";;;AAmCA,oDAIC;AAwDD,4CAgEC;AA/JD,2CAGwB;AAExB,6DAGiC;AAOjC,0DAA0D;AAC7C,QAAA,qCAAqC,GAAG,IAAI,CAAC;AAE7C,QAAA,+BAA+B,GAAG,4BAA4B,CAAC;AAC/D,QAAA,8BAA8B,GAAG,2BAA2B,CAAC;AAE1E;;;;;GAKG;AACH,MAAM,mBAAmB,GAAoB,IAAI,OAAO,EAAU,CAAC;AAEnE,SAAS,sBAAsB,CAAwB,KAAa;IAClE,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAE/B,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAgB,oBAAoB,CAAC,KAAc;IACjD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAChD,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC;QAChC,CAAC,CAAC,KAAK,CAAC;AACZ,CAAC;AAED,SAAS,sBAAsB,CAC7B,IAAY,EACZ,OAAe;IAEf,OAAO,sBAAsB,CAC3B,IAAI,oCAA2B,CAAC;QAC9B,IAAI;QACJ,KAAK,EAAE,qBAAqB;QAC5B,OAAO;QACP,UAAU,EAAE,GAAG;KAChB,CAAC,CACH,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,KAAK,GAAG,KAA0C,CAAC;IAEzD,OAAO,CACL,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;QACjC,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;QAC9B,KAAK,CAAC,MAAM,KAAK,WAAW;QAC5B,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAC7D,CAAC;AACJ,CAAC;AAED,SAAS,uBAAuB,CAC9B,MAAwC;IAExC,OAAO,MAAM,CAAC,GAAG,CACf,CAAC,KAA4B,EAAiB,EAAE,CAAC,CAAC;QAChD,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;KAC1D,CAAC,CACH,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACI,KAAK,UAAU,gBAAgB,CACpC,KAAuB,EACvB,KAA4B,EAC5B,SAAiB;IAEjB,MAAM,YAAY,GAAG,sBAAsB,CACzC,IAAI,KAAK,CAAC,8BAA8B,SAAS,IAAI,CAAC,CACvD,CAAC;IACF,IAAI,KAAiC,CAAC;IAEtC,IAAI,MAAwC,CAAC;IAE7C,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;YAC1B,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAA8C,EAAE,CACrE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CACnB;YACD,IAAI,OAAO,CAAQ,CAAC,QAAQ,EAAE,MAAM,EAAQ,EAAE;gBAC5C,KAAK,GAAG,UAAU,CAAC,GAAS,EAAE;oBAC5B,MAAM,CAAC,YAAY,CAAC,CAAC;gBACvB,CAAC,EAAE,SAAS,CAAC,CAAC;YAChB,CAAC,CAAC;SACH,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;YAC3B,MAAM,sBAAsB,CAC1B,uCAA+B,EAC/B,wCAAwC,SAAS,KAAK,CACvD,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,YAAY,sBAAa,EAAE,CAAC;YACnC,sBAAsB,CAAC,KAAK,CAAC,CAAC;YAE9B,MAAM,KAAK,CAAC;QACd,CAAC;QAED,MAAM,sBAAsB,CAC1B,sCAA8B,EAC9B,uBAAuB,CACxB,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;QAC1D,MAAM,sBAAsB,CAC1B,sCAA8B,EAC9B,sDAAsD,CACvD,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO;IACT,CAAC;IAED,MAAM,cAAc,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAEvD,MAAM,sBAAsB,CAC1B,IAAA,0CAAwB,EACtB,IAAA,0CAAwB,EAAC,cAAc,CAAC,EACxC,cAAc,CACf,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { InjectionToken } from '@nestjs/common';
|
|
2
|
+
import type { WorkflowNode } from '@rytass/bpm-core-shared';
|
|
3
|
+
import type { EntityManager } from 'typeorm';
|
|
4
|
+
import type { BPMAuthContext } from '../bpm-auth';
|
|
5
|
+
import type { ApprovalInstanceEntity } from './approval-instance.entity';
|
|
6
|
+
import type { TaskEntity } from './task.entity';
|
|
7
|
+
import type { ApprovalTemplateVersionEntity } from '../template/approval-template-version.entity';
|
|
8
|
+
/**
|
|
9
|
+
* Which engine path is asking the guard: a case being submitted, a returned
|
|
10
|
+
* case being resubmitted, or a task being decided.
|
|
11
|
+
*/
|
|
12
|
+
export type BPMInstanceGuardKind = 'DECIDE' | 'RESUBMIT' | 'SUBMIT';
|
|
13
|
+
/**
|
|
14
|
+
* What the engine hands the guard. The guard runs inside the engine
|
|
15
|
+
* transaction, after the case lock is taken, so every value here is the state
|
|
16
|
+
* the engine is about to commit.
|
|
17
|
+
*
|
|
18
|
+
* Treat every object as read-only. The guard decides, it does not write:
|
|
19
|
+
* whatever it writes through `manager` is committed or rolled back together
|
|
20
|
+
* with the decision, and a timed-out guard cannot take it back.
|
|
21
|
+
*/
|
|
22
|
+
export interface BPMInstanceGuardInput {
|
|
23
|
+
/** The member who triggered the path, or `null` for a system action. */
|
|
24
|
+
readonly actorMemberId: string | null;
|
|
25
|
+
/**
|
|
26
|
+
* Set only for a decision made by the engine itself (SLA auto-approve). The
|
|
27
|
+
* guard may treat it differently, for example to skip an approver-facing
|
|
28
|
+
* rule. `null` for every other decision.
|
|
29
|
+
*/
|
|
30
|
+
readonly automatic: 'SLA_AUTO_APPROVE' | null;
|
|
31
|
+
/** The caller's auth context, when the path has one. */
|
|
32
|
+
readonly authContext: BPMAuthContext | null;
|
|
33
|
+
/** The decision action (`APPROVE`, `REJECT`, ...). `null` unless `kind` is `DECIDE`. */
|
|
34
|
+
readonly action: string | null;
|
|
35
|
+
/**
|
|
36
|
+
* The keys of `formData` the request changed, sorted. For `SUBMIT` every
|
|
37
|
+
* submitted key counts; for `RESUBMIT` the keys whose value differs from the
|
|
38
|
+
* stored form data, including keys the resubmission drops; for `DECIDE` the
|
|
39
|
+
* approver-filled fields whose value really changes.
|
|
40
|
+
*/
|
|
41
|
+
readonly changedFieldKeys: readonly string[];
|
|
42
|
+
/**
|
|
43
|
+
* The case as it will be committed. For `SUBMIT` this is the entity the
|
|
44
|
+
* engine has just built and not yet saved (no `id` yet).
|
|
45
|
+
*/
|
|
46
|
+
readonly instance: Readonly<ApprovalInstanceEntity>;
|
|
47
|
+
readonly kind: BPMInstanceGuardKind;
|
|
48
|
+
/** The merged form data the case will hold after this path. */
|
|
49
|
+
readonly formData: Readonly<Record<string, unknown>>;
|
|
50
|
+
/** The node being decided. `null` unless `kind` is `DECIDE`. */
|
|
51
|
+
readonly node: WorkflowNode | null;
|
|
52
|
+
/** The task being decided. `null` unless `kind` is `DECIDE`. */
|
|
53
|
+
readonly task: Readonly<TaskEntity> | null;
|
|
54
|
+
/** The published template version the case runs on. */
|
|
55
|
+
readonly templateVersion: Readonly<ApprovalTemplateVersionEntity>;
|
|
56
|
+
/**
|
|
57
|
+
* The engine's transaction manager, for reads that must see the same
|
|
58
|
+
* snapshot the decision is made on. Do not write through it (see above).
|
|
59
|
+
*/
|
|
60
|
+
readonly manager: EntityManager;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* One rule the guard refuses on. A non-empty list is returned to the caller as
|
|
64
|
+
* a 400 `createFormDataBadRequest` carrying `formDataErrors`.
|
|
65
|
+
*
|
|
66
|
+
* - `path` is the form field the rule is about, or `''` for the whole case.
|
|
67
|
+
* - `reason` is always `HOST_RULE` for guard issues.
|
|
68
|
+
* - `code` is an optional host error code, passed through unchanged.
|
|
69
|
+
*
|
|
70
|
+
* A guard returns issues only. It cannot return a patch to `formData`: a
|
|
71
|
+
* patch would bypass the approver-fill permissions and the signature coverage.
|
|
72
|
+
*/
|
|
73
|
+
export interface BPMInstanceGuardIssue {
|
|
74
|
+
readonly code?: string;
|
|
75
|
+
readonly message: string;
|
|
76
|
+
readonly path: string;
|
|
77
|
+
readonly reason: 'HOST_RULE';
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Host hook that can refuse a case before the engine commits a state change.
|
|
81
|
+
*
|
|
82
|
+
* The engine calls `check` on three paths: submit, resubmit and decide. It is
|
|
83
|
+
* called inside the transaction, so a refusal rolls the whole change back. An
|
|
84
|
+
* empty array means pass; a non-empty array becomes a 400. A thrown
|
|
85
|
+
* `HttpException` is returned to the caller unchanged; any other error and a
|
|
86
|
+
* timeout become a 503 (`BPM_INSTANCE_GUARD_FAILED` /
|
|
87
|
+
* `BPM_INSTANCE_GUARD_TIMEOUT`). The default timeout is 5000 ms
|
|
88
|
+
* (`instanceGuardTimeoutMs`).
|
|
89
|
+
*
|
|
90
|
+
* Keep `check` fast and side-effect free. A call that is still running when
|
|
91
|
+
* the timeout fires keeps running; if it has external side effects, the host
|
|
92
|
+
* must make them idempotent itself.
|
|
93
|
+
*/
|
|
94
|
+
export interface BPMInstanceGuard {
|
|
95
|
+
check(input: BPMInstanceGuardInput): Promise<readonly BPMInstanceGuardIssue[]>;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Optional host binding for {@link BPMInstanceGuard}. Without one, the three
|
|
99
|
+
* engine paths behave exactly as before the guard existed.
|
|
100
|
+
*/
|
|
101
|
+
export declare const BPM_INSTANCE_GUARD: InjectionToken<BPMInstanceGuard>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BPM_INSTANCE_GUARD = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Optional host binding for {@link BPMInstanceGuard}. Without one, the three
|
|
6
|
+
* engine paths behave exactly as before the guard existed.
|
|
7
|
+
*/
|
|
8
|
+
exports.BPM_INSTANCE_GUARD = Symbol('BPM_INSTANCE_GUARD');
|
|
9
|
+
//# sourceMappingURL=instance-guard.token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-guard.token.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/workflow-engine/instance-guard.token.ts"],"names":[],"mappings":";;;AAkHA;;;GAGG;AACU,QAAA,kBAAkB,GAAqC,MAAM,CACxE,oBAAoB,CACrB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { FormDefinitionSchema } from '@rytass/bpm-core-shared';
|
|
2
|
+
/**
|
|
3
|
+
* The form data an expression reads when the host turns on
|
|
4
|
+
* `expressionMissingFormFieldsAsNull` (ADR 27 §3): every top-level field of
|
|
5
|
+
* the schema that the data has no key for is added, as `[]` for a table and
|
|
6
|
+
* `null` for anything else. A key that is present is never touched, and the
|
|
7
|
+
* columns inside table rows are not filled.
|
|
8
|
+
*
|
|
9
|
+
* The result is a copy used for evaluation only; it is never written back to
|
|
10
|
+
* `form_data`.
|
|
11
|
+
*/
|
|
12
|
+
export declare function fillMissingFormFields(formData: Readonly<Record<string, unknown>>, schema: FormDefinitionSchema): Readonly<Record<string, unknown>>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fillMissingFormFields = fillMissingFormFields;
|
|
4
|
+
/**
|
|
5
|
+
* The form data an expression reads when the host turns on
|
|
6
|
+
* `expressionMissingFormFieldsAsNull` (ADR 27 §3): every top-level field of
|
|
7
|
+
* the schema that the data has no key for is added, as `[]` for a table and
|
|
8
|
+
* `null` for anything else. A key that is present is never touched, and the
|
|
9
|
+
* columns inside table rows are not filled.
|
|
10
|
+
*
|
|
11
|
+
* The result is a copy used for evaluation only; it is never written back to
|
|
12
|
+
* `form_data`.
|
|
13
|
+
*/
|
|
14
|
+
function fillMissingFormFields(formData, schema) {
|
|
15
|
+
const missing = schema.fields.filter((field) => !Object.prototype.hasOwnProperty.call(formData, field.fieldKey));
|
|
16
|
+
if (missing.length === 0) {
|
|
17
|
+
return formData;
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
...Object.fromEntries(missing.map((field) => [
|
|
21
|
+
field.fieldKey,
|
|
22
|
+
field.type === 'table' ? [] : null,
|
|
23
|
+
])),
|
|
24
|
+
...formData,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=missing-form-fields.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"missing-form-fields.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/workflow-engine/missing-form-fields.ts"],"names":[],"mappings":";;AAYA,sDAsBC;AAhCD;;;;;;;;;GASG;AACH,SAAgB,qBAAqB,CACnC,QAA2C,EAC3C,MAA4B;IAE5B,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAClC,CAAC,KAAK,EAAW,EAAE,CACjB,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAClE,CAAC;IAEF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO;QACL,GAAG,MAAM,CAAC,WAAW,CACnB,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAA8B,EAAE,CAAC;YACjD,KAAK,CAAC,QAAQ;YACd,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI;SACnC,CAAC,CACH;QACD,GAAG,QAAQ;KACZ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { StuckApprovalInstanceKindEnum } from './workflow-engine.enums';
|
|
2
|
+
/**
|
|
3
|
+
* An approval instance that could not move on to its next stage, as the
|
|
4
|
+
* administrator's stuck-instances screen lists it: one row per instance, from
|
|
5
|
+
* its latest unresolved failure.
|
|
6
|
+
*/
|
|
7
|
+
export declare class StuckApprovalInstanceObject {
|
|
8
|
+
instanceId: string;
|
|
9
|
+
instanceTitle: string;
|
|
10
|
+
templateId: string;
|
|
11
|
+
templateName: string | null;
|
|
12
|
+
initiatorMemberId: string;
|
|
13
|
+
kind: StuckApprovalInstanceKindEnum;
|
|
14
|
+
nodeId: string | null;
|
|
15
|
+
nodeLabel: string | null;
|
|
16
|
+
taskId: string | null;
|
|
17
|
+
pendingActorMemberIds: string[];
|
|
18
|
+
failedActorMemberId: string | null;
|
|
19
|
+
automatic: string | null;
|
|
20
|
+
message: string;
|
|
21
|
+
failedAt: Date;
|
|
22
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StuckApprovalInstanceObject = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const graphql_1 = require("@nestjs/graphql");
|
|
6
|
+
const workflow_engine_enums_1 = require("./workflow-engine.enums");
|
|
7
|
+
/**
|
|
8
|
+
* An approval instance that could not move on to its next stage, as the
|
|
9
|
+
* administrator's stuck-instances screen lists it: one row per instance, from
|
|
10
|
+
* its latest unresolved failure.
|
|
11
|
+
*/
|
|
12
|
+
let StuckApprovalInstanceObject = class StuckApprovalInstanceObject {
|
|
13
|
+
};
|
|
14
|
+
exports.StuckApprovalInstanceObject = StuckApprovalInstanceObject;
|
|
15
|
+
tslib_1.__decorate([
|
|
16
|
+
(0, graphql_1.Field)(() => graphql_1.ID, { description: 'The stuck instance.' }),
|
|
17
|
+
tslib_1.__metadata("design:type", String)
|
|
18
|
+
], StuckApprovalInstanceObject.prototype, "instanceId", void 0);
|
|
19
|
+
tslib_1.__decorate([
|
|
20
|
+
(0, graphql_1.Field)({ description: 'Title of the stuck instance.' }),
|
|
21
|
+
tslib_1.__metadata("design:type", String)
|
|
22
|
+
], StuckApprovalInstanceObject.prototype, "instanceTitle", void 0);
|
|
23
|
+
tslib_1.__decorate([
|
|
24
|
+
(0, graphql_1.Field)(() => graphql_1.ID, { description: 'The template the instance was filed from.' }),
|
|
25
|
+
tslib_1.__metadata("design:type", String)
|
|
26
|
+
], StuckApprovalInstanceObject.prototype, "templateId", void 0);
|
|
27
|
+
tslib_1.__decorate([
|
|
28
|
+
(0, graphql_1.Field)(() => String, {
|
|
29
|
+
description: 'Name of that template; null when it can no longer be read.',
|
|
30
|
+
nullable: true,
|
|
31
|
+
}),
|
|
32
|
+
tslib_1.__metadata("design:type", Object)
|
|
33
|
+
], StuckApprovalInstanceObject.prototype, "templateName", void 0);
|
|
34
|
+
tslib_1.__decorate([
|
|
35
|
+
(0, graphql_1.Field)({ description: 'Who filed the instance.' }),
|
|
36
|
+
tslib_1.__metadata("design:type", String)
|
|
37
|
+
], StuckApprovalInstanceObject.prototype, "initiatorMemberId", void 0);
|
|
38
|
+
tslib_1.__decorate([
|
|
39
|
+
(0, graphql_1.Field)(() => workflow_engine_enums_1.StuckApprovalInstanceKindEnum, {
|
|
40
|
+
description: 'DECISION: a decision on a task could not move the instance on. ' +
|
|
41
|
+
'RESUBMIT: the initiator resubmitted a returned instance and it could not start.',
|
|
42
|
+
}),
|
|
43
|
+
tslib_1.__metadata("design:type", String)
|
|
44
|
+
], StuckApprovalInstanceObject.prototype, "kind", void 0);
|
|
45
|
+
tslib_1.__decorate([
|
|
46
|
+
(0, graphql_1.Field)(() => String, {
|
|
47
|
+
description: 'The node the failed decision was made on; null for RESUBMIT.',
|
|
48
|
+
nullable: true,
|
|
49
|
+
}),
|
|
50
|
+
tslib_1.__metadata("design:type", Object)
|
|
51
|
+
], StuckApprovalInstanceObject.prototype, "nodeId", void 0);
|
|
52
|
+
tslib_1.__decorate([
|
|
53
|
+
(0, graphql_1.Field)(() => String, {
|
|
54
|
+
description: 'Display name of that node, read from the instance workflow snapshot; ' +
|
|
55
|
+
'null for RESUBMIT or when the node carries no label.',
|
|
56
|
+
nullable: true,
|
|
57
|
+
}),
|
|
58
|
+
tslib_1.__metadata("design:type", Object)
|
|
59
|
+
], StuckApprovalInstanceObject.prototype, "nodeLabel", void 0);
|
|
60
|
+
tslib_1.__decorate([
|
|
61
|
+
(0, graphql_1.Field)(() => graphql_1.ID, {
|
|
62
|
+
description: 'The task the failed decision was made on; null for RESUBMIT.',
|
|
63
|
+
nullable: true,
|
|
64
|
+
}),
|
|
65
|
+
tslib_1.__metadata("design:type", Object)
|
|
66
|
+
], StuckApprovalInstanceObject.prototype, "taskId", void 0);
|
|
67
|
+
tslib_1.__decorate([
|
|
68
|
+
(0, graphql_1.Field)(() => [String], {
|
|
69
|
+
description: 'Who has to press again now, read when the list is loaded. DECISION: ' +
|
|
70
|
+
'the members whose seat on the task is PENDING or CLAIMED (WAITING ' +
|
|
71
|
+
'seats are not their turn yet), or the assignee of a task that has no ' +
|
|
72
|
+
'candidate rows at all; it follows a later reassignment. RESUBMIT: the ' +
|
|
73
|
+
'initiator only.',
|
|
74
|
+
}),
|
|
75
|
+
tslib_1.__metadata("design:type", Array)
|
|
76
|
+
], StuckApprovalInstanceObject.prototype, "pendingActorMemberIds", void 0);
|
|
77
|
+
tslib_1.__decorate([
|
|
78
|
+
(0, graphql_1.Field)(() => String, {
|
|
79
|
+
description: 'The member the failed attempt was made as. For an automatic approval ' +
|
|
80
|
+
'this is the holder the system picked, who did not press anything: ' +
|
|
81
|
+
'read `automatic` first.',
|
|
82
|
+
nullable: true,
|
|
83
|
+
}),
|
|
84
|
+
tslib_1.__metadata("design:type", Object)
|
|
85
|
+
], StuckApprovalInstanceObject.prototype, "failedActorMemberId", void 0);
|
|
86
|
+
tslib_1.__decorate([
|
|
87
|
+
(0, graphql_1.Field)(() => String, {
|
|
88
|
+
description: "'SLA_AUTO_APPROVE' when the failed attempt was the system approving " +
|
|
89
|
+
'an overdue task, null when a person pressed the button.',
|
|
90
|
+
nullable: true,
|
|
91
|
+
}),
|
|
92
|
+
tslib_1.__metadata("design:type", Object)
|
|
93
|
+
], StuckApprovalInstanceObject.prototype, "automatic", void 0);
|
|
94
|
+
tslib_1.__decorate([
|
|
95
|
+
(0, graphql_1.Field)({
|
|
96
|
+
description: 'Why the instance could not move on, as the operator saw it.',
|
|
97
|
+
}),
|
|
98
|
+
tslib_1.__metadata("design:type", String)
|
|
99
|
+
], StuckApprovalInstanceObject.prototype, "message", void 0);
|
|
100
|
+
tslib_1.__decorate([
|
|
101
|
+
(0, graphql_1.Field)({ description: 'When the failed attempt was recorded.' }),
|
|
102
|
+
tslib_1.__metadata("design:type", Date)
|
|
103
|
+
], StuckApprovalInstanceObject.prototype, "failedAt", void 0);
|
|
104
|
+
exports.StuckApprovalInstanceObject = StuckApprovalInstanceObject = tslib_1.__decorate([
|
|
105
|
+
(0, graphql_1.ObjectType)('StuckApprovalInstance')
|
|
106
|
+
], StuckApprovalInstanceObject);
|
|
107
|
+
//# sourceMappingURL=stuck-approval-instance.object.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stuck-approval-instance.object.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/workflow-engine/stuck-approval-instance.object.ts"],"names":[],"mappings":";;;;AAAA,6CAAwD;AACxD,mEAAwE;AAExE;;;;GAIG;AAEI,IAAM,2BAA2B,GAAjC,MAAM,2BAA2B;CAiFvC,CAAA;AAjFY,kEAA2B;AAEtC;IADC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,YAAE,EAAE,EAAE,WAAW,EAAE,qBAAqB,EAAE,CAAC;;+DACpC;AAGpB;IADC,IAAA,eAAK,EAAC,EAAE,WAAW,EAAE,8BAA8B,EAAE,CAAC;;kEAChC;AAGvB;IADC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,YAAE,EAAE,EAAE,WAAW,EAAE,2CAA2C,EAAE,CAAC;;+DAC1D;AAMpB;IAJC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,MAAM,EAAE;QACnB,WAAW,EAAE,4DAA4D;QACzE,QAAQ,EAAE,IAAI;KACf,CAAC;;iEAC2B;AAG7B;IADC,IAAA,eAAK,EAAC,EAAE,WAAW,EAAE,yBAAyB,EAAE,CAAC;;sEACvB;AAO3B;IALC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,qDAA6B,EAAE;QAC1C,WAAW,EACT,iEAAiE;YACjE,iFAAiF;KACpF,CAAC;;yDACmC;AAOrC;IALC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,MAAM,EAAE;QACnB,WAAW,EACT,8DAA8D;QAChE,QAAQ,EAAE,IAAI;KACf,CAAC;;2DACqB;AAQvB;IANC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,MAAM,EAAE;QACnB,WAAW,EACT,uEAAuE;YACvE,sDAAsD;QACxD,QAAQ,EAAE,IAAI;KACf,CAAC;;8DACwB;AAM1B;IAJC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,YAAE,EAAE;QACf,WAAW,EAAE,8DAA8D;QAC3E,QAAQ,EAAE,IAAI;KACf,CAAC;;2DACqB;AAUvB;IARC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE;QACrB,WAAW,EACT,sEAAsE;YACtE,oEAAoE;YACpE,uEAAuE;YACvE,wEAAwE;YACxE,iBAAiB;KACpB,CAAC;;0EAC+B;AASjC;IAPC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,MAAM,EAAE;QACnB,WAAW,EACT,uEAAuE;YACvE,oEAAoE;YACpE,yBAAyB;QAC3B,QAAQ,EAAE,IAAI;KACf,CAAC;;wEACkC;AAQpC;IANC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,MAAM,EAAE;QACnB,WAAW,EACT,sEAAsE;YACtE,yDAAyD;QAC3D,QAAQ,EAAE,IAAI;KACf,CAAC;;8DACwB;AAK1B;IAHC,IAAA,eAAK,EAAC;QACL,WAAW,EAAE,6DAA6D;KAC3E,CAAC;;4DACe;AAGjB;IADC,IAAA,eAAK,EAAC,EAAE,WAAW,EAAE,uCAAuC,EAAE,CAAC;sCACrD,IAAI;6DAAC;sCAhFL,2BAA2B;IADvC,IAAA,oBAAU,EAAC,uBAAuB,CAAC;GACvB,2BAA2B,CAiFvC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { EntityManager } from 'typeorm';
|
|
2
|
+
import { ActivityLogEntity } from './activity-log.entity';
|
|
3
|
+
import { ApprovalInstanceEntity } from './approval-instance.entity';
|
|
4
|
+
import { TaskStatusEnum } from './workflow-engine.enums';
|
|
5
|
+
/**
|
|
6
|
+
* The rule above for one instance, given its `ADVANCE_FAILED` and
|
|
7
|
+
* `INSTANCE_RESUBMITTED` rows in `seq` order and the ids of the tasks among
|
|
8
|
+
* them that are still open.
|
|
9
|
+
*/
|
|
10
|
+
export declare function readUnresolvedInstanceFailures(instance: ApprovalInstanceEntity, logs: readonly ActivityLogEntity[], openTaskIds: ReadonlySet<string>): readonly ActivityLogEntity[];
|
|
11
|
+
/**
|
|
12
|
+
* One page of stuck instances, as the ids of the failure that describes each:
|
|
13
|
+
* its latest unresolved `ADVANCE_FAILED` (highest `seq`). Newest failure first:
|
|
14
|
+
* `created_at` is the transaction start, so `seq` breaks a tie within one
|
|
15
|
+
* transaction, and the instance id any tie left after that.
|
|
16
|
+
*/
|
|
17
|
+
export declare function readStuckFailurePage(manager: EntityManager, openTaskStatuses: readonly TaskStatusEnum[], page: {
|
|
18
|
+
readonly offset: number;
|
|
19
|
+
readonly limit: number;
|
|
20
|
+
}): Promise<readonly string[]>;
|
|
21
|
+
/** How many instances {@link readStuckFailurePage} pages through. */
|
|
22
|
+
export declare function countStuckInstances(manager: EntityManager, openTaskStatuses: readonly TaskStatusEnum[]): Promise<number>;
|