hierarchical-approval 4.0.2 → 4.0.4

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 (81) hide show
  1. package/CHANGELOG.md +20 -6
  2. package/README.md +1 -1
  3. package/dist/{ApprovalEngine-XgGBQLC_.d.cts → ApprovalEngine-D0_F5OPZ.d.cts} +35 -10
  4. package/dist/{ApprovalEngine-Dqe-rC6K.d.ts → ApprovalEngine-D4bXQrKD.d.ts} +35 -10
  5. package/dist/Clock-D8Qp39q_.d.cts +8 -0
  6. package/dist/Clock-D8Qp39q_.d.ts +8 -0
  7. package/dist/{IAuditAdapter-Dt8qjkQL.d.cts → IAuditAdapter-D9WE0t7A.d.cts} +2 -1
  8. package/dist/{IAuditAdapter-DkbyFFjb.d.ts → IAuditAdapter-FI_RF_XU.d.ts} +2 -1
  9. package/dist/{IAuthorizationPolicy-YJ_08Mof.d.cts → IAuthorizationPolicy-BKKw7jGN.d.ts} +6 -1
  10. package/dist/{IAuthorizationPolicy-eo6glbpE.d.ts → IAuthorizationPolicy-DDmjeYV-.d.cts} +6 -1
  11. package/dist/{IMetricsAdapter-DWq8IFaf.d.cts → IMetricsAdapter-WROxYSXd.d.cts} +1 -0
  12. package/dist/{IMetricsAdapter-DWq8IFaf.d.ts → IMetricsAdapter-WROxYSXd.d.ts} +1 -0
  13. package/dist/{INotificationAdapter-BTO9FSKy.d.ts → INotificationAdapter-CLROEfRd.d.ts} +26 -1
  14. package/dist/{INotificationAdapter-XbD69gss.d.cts → INotificationAdapter-J0wSPLIC.d.cts} +26 -1
  15. package/dist/{IOperationMiddleware-CX7lo4lp.d.ts → IOperationMiddleware-B32a2dwP.d.ts} +15 -2
  16. package/dist/{IOperationMiddleware-BBLk8MIz.d.cts → IOperationMiddleware-UUKqztxM.d.cts} +15 -2
  17. package/dist/{ISchedulerAdapter-DKv_QjVN.d.cts → ISchedulerAdapter-CLMdBA-5.d.cts} +1 -0
  18. package/dist/{ISchedulerAdapter-DKv_QjVN.d.ts → ISchedulerAdapter-CLMdBA-5.d.ts} +1 -0
  19. package/dist/{IStorageAdapter-CdXMggPK.d.ts → IStorageAdapter-DSKJ1onF.d.ts} +14 -1
  20. package/dist/{IStorageAdapter-Cjw5zDwQ.d.cts → IStorageAdapter-Dhrc4ES6.d.cts} +14 -1
  21. package/dist/{Logger-BplhlU7l.d.cts → Logger-hqFbBCtB.d.cts} +7 -0
  22. package/dist/{Logger-BplhlU7l.d.ts → Logger-hqFbBCtB.d.ts} +7 -0
  23. package/dist/adapters/MemoryAdapter.cjs.map +1 -1
  24. package/dist/adapters/MemoryAdapter.d.cts +2 -2
  25. package/dist/adapters/MemoryAdapter.d.ts +2 -2
  26. package/dist/adapters/MemoryAdapter.js.map +1 -1
  27. package/dist/adapters/PostgresAdapter.cjs.map +1 -1
  28. package/dist/adapters/PostgresAdapter.d.cts +2 -2
  29. package/dist/adapters/PostgresAdapter.d.ts +2 -2
  30. package/dist/adapters/PostgresAdapter.js.map +1 -1
  31. package/dist/index.cjs +51 -8
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.d.cts +14 -14
  34. package/dist/index.d.ts +14 -14
  35. package/dist/index.js +51 -8
  36. package/dist/index.js.map +1 -1
  37. package/dist/{instance-uUQh5XW3.d.cts → instance-CUZcHWK2.d.cts} +28 -0
  38. package/dist/{instance-uUQh5XW3.d.ts → instance-CUZcHWK2.d.ts} +28 -0
  39. package/dist/nestjs.cjs +61 -7
  40. package/dist/nestjs.cjs.map +1 -1
  41. package/dist/nestjs.d.cts +22 -11
  42. package/dist/nestjs.d.ts +22 -11
  43. package/dist/nestjs.js +61 -7
  44. package/dist/nestjs.js.map +1 -1
  45. package/dist/plugins/audit.cjs.map +1 -1
  46. package/dist/plugins/audit.d.cts +3 -3
  47. package/dist/plugins/audit.d.ts +3 -3
  48. package/dist/plugins/audit.js.map +1 -1
  49. package/dist/plugins/metrics.cjs.map +1 -1
  50. package/dist/plugins/metrics.d.cts +2 -2
  51. package/dist/plugins/metrics.d.ts +2 -2
  52. package/dist/plugins/metrics.js.map +1 -1
  53. package/dist/plugins/notify.cjs.map +1 -1
  54. package/dist/plugins/notify.d.cts +4 -4
  55. package/dist/plugins/notify.d.ts +4 -4
  56. package/dist/plugins/notify.js.map +1 -1
  57. package/dist/plugins/resilience.cjs.map +1 -1
  58. package/dist/plugins/resilience.d.cts +5 -5
  59. package/dist/plugins/resilience.d.ts +5 -5
  60. package/dist/plugins/resilience.js.map +1 -1
  61. package/dist/plugins/scheduler.cjs.map +1 -1
  62. package/dist/plugins/scheduler.d.cts +3 -3
  63. package/dist/plugins/scheduler.d.ts +3 -3
  64. package/dist/plugins/scheduler.js.map +1 -1
  65. package/dist/plugins/tracing.cjs.map +1 -1
  66. package/dist/plugins/tracing.d.cts +4 -2
  67. package/dist/plugins/tracing.d.ts +4 -2
  68. package/dist/plugins/tracing.js.map +1 -1
  69. package/dist/plugins/webhook.cjs.map +1 -1
  70. package/dist/plugins/webhook.d.cts +4 -4
  71. package/dist/plugins/webhook.d.ts +4 -4
  72. package/dist/plugins/webhook.js.map +1 -1
  73. package/dist/testing.cjs +50 -7
  74. package/dist/testing.cjs.map +1 -1
  75. package/dist/testing.d.cts +11 -11
  76. package/dist/testing.d.ts +11 -11
  77. package/dist/testing.js +50 -7
  78. package/dist/testing.js.map +1 -1
  79. package/package.json +1 -1
  80. package/dist/Clock-3FnOczFJ.d.cts +0 -6
  81. package/dist/Clock-3FnOczFJ.d.ts +0 -6
@@ -13,18 +13,28 @@ type ApproverConfig = {
13
13
  type: string;
14
14
  [key: string]: unknown;
15
15
  };
16
+ /** An {@link ApproverConfig} resolved down to a concrete user. */
16
17
  interface ResolvedApprover {
17
18
  userId: string;
19
+ /** The config entry this approver was resolved from. */
18
20
  source: ApproverConfig;
19
21
  }
22
+ /**
23
+ * Resolves a `{ type: 'dynamic' }` approver to a concrete user id, given the
24
+ * submitter and the document's data. Registered via
25
+ * {@link ApprovalEngine.registerResolver}.
26
+ */
20
27
  type ResolverFn = (submittedBy: string, data: Record<string, unknown>) => Promise<string> | string;
21
28
 
22
29
  type ApprovalMode = 'all' | 'any' | 'majority' | 'quorum' | 'weighted';
23
30
  /** Built-in operators. Use engine.registerConditionOperator() to add custom ones. */
24
31
  type ConditionOperator = '>' | '<' | '>=' | '<=' | '==' | '!=' | 'in' | 'not_in' | (string & {});
32
+ /** A single test comparing a field on the evaluated document against a value. */
25
33
  interface Condition {
34
+ /** Dot path into the document being evaluated, e.g. `"amount"` or `"header.total"`. */
26
35
  field: string;
27
36
  operator: ConditionOperator;
37
+ /** The value `field` is compared against; its shape depends on `operator`. */
28
38
  value: unknown;
29
39
  }
30
40
  interface ApprovalLevelConfig {
@@ -145,8 +155,11 @@ interface ConditionRule {
145
155
  addLevels?: ApprovalLevelConfig[];
146
156
  skipLevels?: number[];
147
157
  }
158
+ /** A single-rung escalation. See {@link EscalationStep} for a multi-rung ladder. */
148
159
  interface EscalationConfig {
160
+ /** Delay from the level opening, in calendar or business days. */
149
161
  afterDays: number;
162
+ /** Who is added to the level once `afterDays` elapses. */
150
163
  escalateTo: ApproverConfig;
151
164
  }
152
165
  /** One rung of an escalation ladder. See {@link ApprovalTemplateConfig.escalationSteps}. */
@@ -215,19 +228,33 @@ interface ApprovalTemplate extends ApprovalTemplateConfig {
215
228
  type ApprovalStatus = 'pending' | 'approved' | 'rejected' | 'cancelled' | 'expired';
216
229
  type LevelStatus = 'waiting' | 'pending' | 'approved' | 'rejected' | 'skipped';
217
230
  type AuditAction = 'submitted' | 'approved' | 'rejected' | 'delegated' | 'reassigned' | 'escalated' | 'cancelled' | 'level_advanced' | 'commented' | 'resubmitted' | 'overridden' | 'data_updated' | 'reminded' | 'info_requested' | 'info_provided' | 'attachment_added' | 'attachment_removed' | 'subworkflow_started' | 'subworkflow_completed' | 'expired';
231
+ /** One row of an {@link ApprovalInstance}'s audit log, recording a single state change. */
218
232
  interface AuditEntry {
233
+ /** What happened. */
219
234
  action: AuditAction;
235
+ /** Id of the user or system that performed the action. */
220
236
  actorId: string;
237
+ /** Role the actor held at the time, when supplied via {@link AuditContext}. */
221
238
  actorRole?: string;
239
+ /** IP address the action originated from, when supplied via {@link AuditContext}. */
222
240
  actorIp?: string;
241
+ /** User agent the action originated from, when supplied via {@link AuditContext}. */
223
242
  actorUserAgent?: string;
243
+ /** Level the action applied to, or the current level for instance-wide actions. */
224
244
  level: number;
245
+ /** When the action happened. */
225
246
  timestamp: Date;
247
+ /** Caller-supplied trace id for correlating this entry with external logs. */
226
248
  traceId?: string;
249
+ /** Free-text comment attached to the action, if any. */
227
250
  comment?: string;
251
+ /** Reason given for the action (e.g. a rejection or override reason), if any. */
228
252
  reason?: string;
253
+ /** Id of the user this action routed to, for `'delegated'`/`'reassigned'`/`'escalated'` actions. */
229
254
  delegateTo?: string;
255
+ /** State the action changed from, shaped differently per {@link action}. */
230
256
  oldValue?: Record<string, unknown>;
257
+ /** State the action changed to, shaped differently per {@link action}. */
231
258
  newValue?: Record<string, unknown>;
232
259
  }
233
260
  /** Context injected by the caller on each mutating operation (for SOX/SOC2 compliance). */
@@ -237,6 +264,7 @@ interface AuditContext {
237
264
  actorUserAgent?: string;
238
265
  traceId?: string;
239
266
  }
267
+ /** Runtime state of one level within an {@link ApprovalInstance} — its resolved approvers and how far it has progressed. */
240
268
  interface ApprovalLevelInstance {
241
269
  level: number;
242
270
  name: string;
@@ -13,18 +13,28 @@ type ApproverConfig = {
13
13
  type: string;
14
14
  [key: string]: unknown;
15
15
  };
16
+ /** An {@link ApproverConfig} resolved down to a concrete user. */
16
17
  interface ResolvedApprover {
17
18
  userId: string;
19
+ /** The config entry this approver was resolved from. */
18
20
  source: ApproverConfig;
19
21
  }
22
+ /**
23
+ * Resolves a `{ type: 'dynamic' }` approver to a concrete user id, given the
24
+ * submitter and the document's data. Registered via
25
+ * {@link ApprovalEngine.registerResolver}.
26
+ */
20
27
  type ResolverFn = (submittedBy: string, data: Record<string, unknown>) => Promise<string> | string;
21
28
 
22
29
  type ApprovalMode = 'all' | 'any' | 'majority' | 'quorum' | 'weighted';
23
30
  /** Built-in operators. Use engine.registerConditionOperator() to add custom ones. */
24
31
  type ConditionOperator = '>' | '<' | '>=' | '<=' | '==' | '!=' | 'in' | 'not_in' | (string & {});
32
+ /** A single test comparing a field on the evaluated document against a value. */
25
33
  interface Condition {
34
+ /** Dot path into the document being evaluated, e.g. `"amount"` or `"header.total"`. */
26
35
  field: string;
27
36
  operator: ConditionOperator;
37
+ /** The value `field` is compared against; its shape depends on `operator`. */
28
38
  value: unknown;
29
39
  }
30
40
  interface ApprovalLevelConfig {
@@ -145,8 +155,11 @@ interface ConditionRule {
145
155
  addLevels?: ApprovalLevelConfig[];
146
156
  skipLevels?: number[];
147
157
  }
158
+ /** A single-rung escalation. See {@link EscalationStep} for a multi-rung ladder. */
148
159
  interface EscalationConfig {
160
+ /** Delay from the level opening, in calendar or business days. */
149
161
  afterDays: number;
162
+ /** Who is added to the level once `afterDays` elapses. */
150
163
  escalateTo: ApproverConfig;
151
164
  }
152
165
  /** One rung of an escalation ladder. See {@link ApprovalTemplateConfig.escalationSteps}. */
@@ -215,19 +228,33 @@ interface ApprovalTemplate extends ApprovalTemplateConfig {
215
228
  type ApprovalStatus = 'pending' | 'approved' | 'rejected' | 'cancelled' | 'expired';
216
229
  type LevelStatus = 'waiting' | 'pending' | 'approved' | 'rejected' | 'skipped';
217
230
  type AuditAction = 'submitted' | 'approved' | 'rejected' | 'delegated' | 'reassigned' | 'escalated' | 'cancelled' | 'level_advanced' | 'commented' | 'resubmitted' | 'overridden' | 'data_updated' | 'reminded' | 'info_requested' | 'info_provided' | 'attachment_added' | 'attachment_removed' | 'subworkflow_started' | 'subworkflow_completed' | 'expired';
231
+ /** One row of an {@link ApprovalInstance}'s audit log, recording a single state change. */
218
232
  interface AuditEntry {
233
+ /** What happened. */
219
234
  action: AuditAction;
235
+ /** Id of the user or system that performed the action. */
220
236
  actorId: string;
237
+ /** Role the actor held at the time, when supplied via {@link AuditContext}. */
221
238
  actorRole?: string;
239
+ /** IP address the action originated from, when supplied via {@link AuditContext}. */
222
240
  actorIp?: string;
241
+ /** User agent the action originated from, when supplied via {@link AuditContext}. */
223
242
  actorUserAgent?: string;
243
+ /** Level the action applied to, or the current level for instance-wide actions. */
224
244
  level: number;
245
+ /** When the action happened. */
225
246
  timestamp: Date;
247
+ /** Caller-supplied trace id for correlating this entry with external logs. */
226
248
  traceId?: string;
249
+ /** Free-text comment attached to the action, if any. */
227
250
  comment?: string;
251
+ /** Reason given for the action (e.g. a rejection or override reason), if any. */
228
252
  reason?: string;
253
+ /** Id of the user this action routed to, for `'delegated'`/`'reassigned'`/`'escalated'` actions. */
229
254
  delegateTo?: string;
255
+ /** State the action changed from, shaped differently per {@link action}. */
230
256
  oldValue?: Record<string, unknown>;
257
+ /** State the action changed to, shaped differently per {@link action}. */
231
258
  newValue?: Record<string, unknown>;
232
259
  }
233
260
  /** Context injected by the caller on each mutating operation (for SOX/SOC2 compliance). */
@@ -237,6 +264,7 @@ interface AuditContext {
237
264
  actorUserAgent?: string;
238
265
  traceId?: string;
239
266
  }
267
+ /** Runtime state of one level within an {@link ApprovalInstance} — its resolved approvers and how far it has progressed. */
240
268
  interface ApprovalLevelInstance {
241
269
  level: number;
242
270
  name: string;
package/dist/nestjs.cjs CHANGED
@@ -557,6 +557,7 @@ var TemplateRegistry = class {
557
557
  delete resolved.removeLevels;
558
558
  return resolved;
559
559
  }
560
+ /** Register a new template. Throws if a template with this name already exists for the tenant. */
560
561
  async define(config) {
561
562
  const existing = await this.adapter.getTemplate(this.tenantId, config.name);
562
563
  if (existing) {
@@ -593,11 +594,13 @@ var TemplateRegistry = class {
593
594
  await this.adapter.saveTemplate(updated);
594
595
  return newId;
595
596
  }
597
+ /** Fetch a template by name. Throws if no template with this name exists for the tenant. */
596
598
  async get(name) {
597
599
  const template = await this.adapter.getTemplate(this.tenantId, name);
598
600
  if (!template) throw new ApprovalTemplateNotFoundError(name);
599
601
  return template;
600
602
  }
603
+ /** List every template registered for the tenant. */
601
604
  async list() {
602
605
  return this.adapter.listTemplates(this.tenantId);
603
606
  }
@@ -637,6 +640,32 @@ var LevelResolver = class {
637
640
  for (const [name, fn] of this.resolvers) target.register(name, fn);
638
641
  for (const [name, fn] of this.approverTypes) target.registerApproverType(name, fn);
639
642
  }
643
+ /**
644
+ * Resolve a level's `approvers` config down to a deduplicated list of user
645
+ * ids, applying out-of-office cover last so a substitute never sees a stale
646
+ * approver id.
647
+ *
648
+ * @param approvers - The level's approver configs (`user`, `role`,
649
+ * `dynamic`, or a custom type registered via {@link registerApproverType}).
650
+ * @param submittedBy - Passed through to `dynamic` resolvers and custom
651
+ * approver-type functions as routing context.
652
+ * @param data - The instance's document data, passed through the same way.
653
+ * @param orgProvider - Required to resolve `role` approvers; omit only when
654
+ * the template uses no `role` approvers.
655
+ * @param outOfOffice - Optional cover lookup, consulted after every other
656
+ * approver type has resolved.
657
+ * @param at - The moment out-of-office cover is resolved for. Defaults to
658
+ * now.
659
+ * @param substitutions - Filled with `original -> stand-in` for each
660
+ * approver replaced by out-of-office cover, so the caller can carry
661
+ * anything keyed by the original id (such as a weighted level's vote
662
+ * weight) across to the substitute.
663
+ * @returns The resolved, deduplicated approver ids (post-substitution).
664
+ * @throws {ApprovalValidationError} If no approvers resolve at all, a
665
+ * `role` approver is configured without an `orgProvider`, a `dynamic`
666
+ * approver names a resolver that was never registered, or a custom
667
+ * approver type was never registered.
668
+ */
640
669
  async resolveApprovers(approvers, submittedBy, data, orgProvider, outOfOffice, at, substitutions) {
641
670
  const resolved = [];
642
671
  for (const approver of approvers) {
@@ -1048,7 +1077,7 @@ function evaluateConditions(conditions, data) {
1048
1077
  function assertStatus(instance, expected) {
1049
1078
  if (instance.status !== expected) {
1050
1079
  throw new ApprovalError(
1051
- `Expected instance status "${expected}" but got "${instance.status}".`,
1080
+ `Instance "${instance.id}": expected status "${expected}" but got "${instance.status}".`,
1052
1081
  "INVALID_STATUS"
1053
1082
  );
1054
1083
  }
@@ -1056,7 +1085,7 @@ function assertStatus(instance, expected) {
1056
1085
  function assertApproverOnLevel(level, approverId) {
1057
1086
  if (!level.approverIds.includes(approverId)) {
1058
1087
  throw new ApprovalForbiddenError(
1059
- `User "${approverId}" is not an approver for level ${level.level}.`
1088
+ `User "${approverId}" is not an approver for level ${level.level} ("${level.name}").`
1060
1089
  );
1061
1090
  }
1062
1091
  }
@@ -2100,7 +2129,7 @@ var ApprovalEngine = class _ApprovalEngine {
2100
2129
  await this.withOptimisticRetry(instanceId, async (instance) => {
2101
2130
  assertStatus(instance, "pending");
2102
2131
  if (opts.fromApprover === opts.toApprover) {
2103
- throw new ApprovalForbiddenError("Cannot delegate to yourself.");
2132
+ throw new ApprovalForbiddenError(`Cannot delegate to yourself: "${opts.fromApprover}".`);
2104
2133
  }
2105
2134
  const level = this.resolveActorLevel(instance, opts.fromApprover, opts.level);
2106
2135
  this.inheritWeight(level, opts.fromApprover, opts.toApprover);
@@ -2183,7 +2212,9 @@ var ApprovalEngine = class _ApprovalEngine {
2183
2212
  return this.withOptimisticRetry(instanceId, async (instance) => {
2184
2213
  assertStatus(instance, "pending");
2185
2214
  if (opts.fromApprover === opts.toApprover) {
2186
- throw new ApprovalForbiddenError("Cannot reassign an approver to themselves.");
2215
+ throw new ApprovalForbiddenError(
2216
+ `Cannot reassign an approver to themselves: "${opts.fromApprover}".`
2217
+ );
2187
2218
  }
2188
2219
  const level = this.resolveActorLevel(instance, opts.fromApprover, opts.level);
2189
2220
  this.inheritWeight(level, opts.fromApprover, opts.toApprover);
@@ -3009,7 +3040,15 @@ var ApprovalEngine = class _ApprovalEngine {
3009
3040
  }
3010
3041
  const levelNums = new Set(allLevelCfgs.map((l) => l.level));
3011
3042
  if (levelNums.size !== allLevelCfgs.length) {
3012
- throw new ApprovalValidationError("Duplicate level numbers after condition evaluation.");
3043
+ const seen = /* @__PURE__ */ new Set();
3044
+ const duplicates = /* @__PURE__ */ new Set();
3045
+ for (const l of allLevelCfgs) {
3046
+ if (seen.has(l.level)) duplicates.add(l.level);
3047
+ seen.add(l.level);
3048
+ }
3049
+ throw new ApprovalValidationError(
3050
+ `Duplicate level numbers after condition evaluation: ${[...duplicates].join(", ")}.`
3051
+ );
3013
3052
  }
3014
3053
  const now = this.clock.now();
3015
3054
  const newInstanceId = this.generateId("inst");
@@ -3381,7 +3420,9 @@ var ApprovalEngine = class _ApprovalEngine {
3381
3420
  );
3382
3421
  }
3383
3422
  if (opts.overriddenBy === instance.submittedBy) {
3384
- throw new ApprovalForbiddenError("Override cannot be performed by the original submitter.");
3423
+ throw new ApprovalForbiddenError(
3424
+ `Override cannot be performed by the original submitter: "${opts.overriddenBy}".`
3425
+ );
3385
3426
  }
3386
3427
  await this.runAuthorizationPolicy({
3387
3428
  operation: "override",
@@ -3875,7 +3916,9 @@ var ApprovalEngine = class _ApprovalEngine {
3875
3916
  const dryRun = opts.dryRun ?? false;
3876
3917
  const limit = opts.limit ?? DEFAULT_PURGE_LIMIT;
3877
3918
  if (!(opts.olderThan instanceof Date) || Number.isNaN(opts.olderThan.getTime())) {
3878
- throw new ApprovalValidationError("purgeInstances requires a valid olderThan date.");
3919
+ throw new ApprovalValidationError(
3920
+ `purgeInstances requires a valid olderThan date, got ${String(opts.olderThan)}.`
3921
+ );
3879
3922
  }
3880
3923
  const requested = opts.statuses ?? [...TERMINAL_STATUSES];
3881
3924
  const nonTerminal = requested.filter((st) => !TERMINAL_STATUSES.has(st));
@@ -5114,6 +5157,11 @@ var HierarchicalApprovalModule = class _HierarchicalApprovalModule {
5114
5157
  constructor(engine) {
5115
5158
  this.engine = engine;
5116
5159
  }
5160
+ /**
5161
+ * Build the module synchronously from a fixed set of engine options.
5162
+ * @param options - Engine configuration plus {@link HierarchicalApprovalModuleOptions.isGlobal}.
5163
+ * @returns A Nest `DynamicModule` exporting the engine under {@link APPROVAL_ENGINE}.
5164
+ */
5117
5165
  static forRoot(options) {
5118
5166
  const { isGlobal, ...engineOptions } = options;
5119
5167
  const engineProvider = {
@@ -5127,6 +5175,12 @@ var HierarchicalApprovalModule = class _HierarchicalApprovalModule {
5127
5175
  exports: [APPROVAL_ENGINE]
5128
5176
  };
5129
5177
  }
5178
+ /**
5179
+ * Build the module with engine options resolved asynchronously, e.g. from a
5180
+ * `ConfigService` injected via {@link HierarchicalApprovalModuleAsyncOptions.inject}.
5181
+ * @param options - Async factory and its imports/injected providers.
5182
+ * @returns A Nest `DynamicModule` exporting the engine under {@link APPROVAL_ENGINE}.
5183
+ */
5130
5184
  static forRootAsync(options) {
5131
5185
  const engineProvider = {
5132
5186
  provide: APPROVAL_ENGINE,