hierarchical-approval 2.4.0 → 2.6.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 +71 -0
- package/README.md +54 -0
- package/dist/{ApprovalEngine-C1dUPnLM.d.cts → ApprovalEngine-BWrblNQ0.d.cts} +81 -7
- package/dist/{ApprovalEngine-Ci9urTDI.d.ts → ApprovalEngine-D4DdSx-M.d.ts} +81 -7
- package/dist/{IAuditAdapter-BHVKMMv6.d.cts → IAuditAdapter-2UU5edKG.d.cts} +1 -1
- package/dist/{IAuditAdapter-C4OASS6u.d.ts → IAuditAdapter-DSor54iY.d.ts} +1 -1
- package/dist/{IAuthorizationPolicy-BA_m2Dg9.d.ts → IAuthorizationPolicy-BOWg-3AH.d.ts} +1 -1
- package/dist/{IAuthorizationPolicy-CtLkwQ8I.d.cts → IAuthorizationPolicy-DPpiKzyh.d.cts} +1 -1
- package/dist/{INotificationAdapter-BdgfUrIn.d.ts → INotificationAdapter-BNGivLgU.d.ts} +1 -1
- package/dist/{INotificationAdapter-JJAiMyMd.d.cts → INotificationAdapter-C6HPrzh6.d.cts} +1 -1
- package/dist/{IOperationMiddleware-BGYrAqep.d.ts → IOperationMiddleware-CXtg2wzF.d.ts} +1 -1
- package/dist/{IOperationMiddleware-D0ksiFM3.d.cts → IOperationMiddleware-CxnPzpqL.d.cts} +1 -1
- package/dist/{IStorageAdapter-BU3sau5W.d.ts → IStorageAdapter-ChPT7ZDp.d.ts} +1 -1
- package/dist/{IStorageAdapter-DdHO4Rf1.d.cts → IStorageAdapter-yX9ERfQE.d.cts} +1 -1
- package/dist/adapters/MemoryAdapter.d.cts +2 -2
- package/dist/adapters/MemoryAdapter.d.ts +2 -2
- package/dist/adapters/PostgresAdapter.d.cts +2 -2
- package/dist/adapters/PostgresAdapter.d.ts +2 -2
- package/dist/index.cjs +179 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -8
- package/dist/index.d.ts +8 -8
- package/dist/index.js +179 -12
- package/dist/index.js.map +1 -1
- package/dist/{instance-DUJY_Axf.d.cts → instance-weh2w7Ji.d.cts} +39 -1
- package/dist/{instance-DUJY_Axf.d.ts → instance-weh2w7Ji.d.ts} +39 -1
- package/dist/nestjs.cjs +111 -11
- package/dist/nestjs.cjs.map +1 -1
- package/dist/nestjs.d.cts +7 -7
- package/dist/nestjs.d.ts +7 -7
- package/dist/nestjs.js +111 -11
- package/dist/nestjs.js.map +1 -1
- package/dist/plugins/audit.d.cts +2 -2
- package/dist/plugins/audit.d.ts +2 -2
- package/dist/plugins/notify.d.cts +2 -2
- package/dist/plugins/notify.d.ts +2 -2
- package/dist/plugins/resilience.d.cts +3 -3
- package/dist/plugins/resilience.d.ts +3 -3
- package/dist/plugins/tracing.d.cts +2 -2
- package/dist/plugins/tracing.d.ts +2 -2
- package/dist/plugins/webhook.d.cts +2 -2
- package/dist/plugins/webhook.d.ts +2 -2
- package/dist/testing.cjs +111 -11
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +7 -7
- package/dist/testing.d.ts +7 -7
- package/dist/testing.js +111 -11
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,77 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
7
7
|
|
|
8
8
|
_Nothing yet._
|
|
9
9
|
|
|
10
|
+
## [2.6.0] - 2026-09-04
|
|
11
|
+
|
|
12
|
+
### Added — escalation ladders
|
|
13
|
+
|
|
14
|
+
- **`escalationSteps` escalates repeatedly, up a chain.** A single `escalation`
|
|
15
|
+
could only ever fire once, so a request that stalled past its second deadline
|
|
16
|
+
had nowhere further to go — the usual "chase the manager, then the director,
|
|
17
|
+
then the VP" pattern had to be built outside the engine, on top of the events.
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
escalationSteps: [
|
|
21
|
+
{ afterDays: 2, escalateTo: { type: 'user', userId: 'director' } },
|
|
22
|
+
{ afterDays: 4, escalateTo: { type: 'user', userId: 'vp' } },
|
|
23
|
+
{ afterDays: 7, escalateTo: { type: 'role', role: 'exec' } },
|
|
24
|
+
]
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Rungs are sorted by delay and fire in order, each **adding** an approver rather
|
|
28
|
+
than replacing one: escalation widens the pool, it does not hand the work over.
|
|
29
|
+
|
|
30
|
+
- **Delays are measured from when the level opened, not from the previous
|
|
31
|
+
escalation**, so a ladder reads the way it is written. The level's opening
|
|
32
|
+
time is recovered from its `submitted` / `level_advanced` audit entry.
|
|
33
|
+
|
|
34
|
+
- Rungs accept `afterHours` as well as `afterDays`, counted through the
|
|
35
|
+
working-hours calendar from 2.5.0 when one is configured. A per-level
|
|
36
|
+
`escalationAfterDays`/`escalationAfterHours` still decides *when* the first
|
|
37
|
+
rung fires — it is the more specific statement about that level — while the
|
|
38
|
+
ladder supplies *who*.
|
|
39
|
+
|
|
40
|
+
- Templates carrying only the single-step `escalation` behave exactly as before;
|
|
41
|
+
the ladder takes precedence when both are set. Levels track progress in
|
|
42
|
+
`escalationStep`, and the ladder is captured in the template snapshot, so an
|
|
43
|
+
in-flight approval keeps the ladder it was submitted under.
|
|
44
|
+
|
|
45
|
+
New exports: `EscalationStep`. `ApprovalTemplateConfig` gains
|
|
46
|
+
`escalationSteps`; levels gain `escalationStep`.
|
|
47
|
+
|
|
48
|
+
## [2.5.0] - 2026-09-04
|
|
49
|
+
|
|
50
|
+
### Added — deadlines in working hours
|
|
51
|
+
|
|
52
|
+
- **`escalationAfterHours` on a level and `slaDeadlineHours` on a template.**
|
|
53
|
+
Deadlines were whole days, but ERP SLAs are quoted in hours far more often —
|
|
54
|
+
"respond within four working hours" — and approximating that as a fraction of
|
|
55
|
+
a day counted evenings and weekends, so a request submitted at 16:00 on a
|
|
56
|
+
Friday was overdue before anybody could have looked at it.
|
|
57
|
+
|
|
58
|
+
- **`businessHoursCalendar({ workdayStartHour, workdayEndHour, weekendDays,
|
|
59
|
+
holidays })`** advances the clock only through the configured working window.
|
|
60
|
+
A `from` outside working hours is first moved to the next working moment, so a
|
|
61
|
+
deadline never starts counting from a time nobody was at work.
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
const engine = new ApprovalEngine({
|
|
65
|
+
adapter,
|
|
66
|
+
calendar: businessHoursCalendar({ workdayStartHour: 9, workdayEndHour: 17 }),
|
|
67
|
+
});
|
|
68
|
+
// Friday 16:00 + 4 working hours -> Monday 12:00
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
- **`BusinessCalendar.addBusinessHours` is optional.** `weekendCalendar` knows
|
|
72
|
+
whole days only; given an hour-based deadline the engine falls back to elapsed
|
|
73
|
+
clock time rather than quietly pretending the calendar was applied. A custom
|
|
74
|
+
calendar opts in by implementing the method.
|
|
75
|
+
|
|
76
|
+
- `validateTemplate()` rejects setting both units on the same level or template,
|
|
77
|
+
and non-positive hour values.
|
|
78
|
+
|
|
79
|
+
New exports: `businessHoursCalendar`, `BusinessHoursCalendarOptions`.
|
|
80
|
+
|
|
10
81
|
## [2.4.0] - 2026-09-04
|
|
11
82
|
|
|
12
83
|
### Added — `DigestNotificationAdapter`
|
package/README.md
CHANGED
|
@@ -468,6 +468,60 @@ The sweep is **not atomic**: it reports per-instance failures rather than rollin
|
|
|
468
468
|
back. A partial transfer is the useful outcome — the approvals that can move
|
|
469
469
|
should move, and the ones that cannot are named so a human can look at them.
|
|
470
470
|
|
|
471
|
+
### Escalation ladders
|
|
472
|
+
|
|
473
|
+
A single `escalation` fires once, so a request that stalls past its second
|
|
474
|
+
deadline has nowhere further to go. `escalationSteps` is a ladder:
|
|
475
|
+
|
|
476
|
+
```ts
|
|
477
|
+
escalationSteps: [
|
|
478
|
+
{ afterDays: 2, escalateTo: { type: 'user', userId: 'director' } },
|
|
479
|
+
{ afterDays: 4, escalateTo: { type: 'user', userId: 'vp' } },
|
|
480
|
+
{ afterDays: 7, escalateTo: { type: 'role', role: 'exec' } },
|
|
481
|
+
]
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
Rungs are sorted by delay and fire in order, each **adding** an approver without
|
|
485
|
+
removing anyone already assigned — escalation widens the pool rather than
|
|
486
|
+
handing the work over.
|
|
487
|
+
|
|
488
|
+
Every delay is measured **from the moment the level opened**, not from the
|
|
489
|
+
previous escalation, so the ladder reads the way it is written: late at day 2,
|
|
490
|
+
later at day 4, latest at day 7. Rungs accept `afterHours` too, counted through
|
|
491
|
+
the working-hours calendar if one is configured.
|
|
492
|
+
|
|
493
|
+
A per-level `escalationAfterDays`/`escalationAfterHours` still wins for *when*
|
|
494
|
+
the first rung fires — it is the more specific statement about that level — while
|
|
495
|
+
the ladder supplies *who*. Templates with only the single-step `escalation`
|
|
496
|
+
behave exactly as before.
|
|
497
|
+
|
|
498
|
+
### SLAs in working hours
|
|
499
|
+
|
|
500
|
+
Deadlines were whole days, so "respond within four working hours" could only be
|
|
501
|
+
approximated. Levels take `escalationAfterHours` and templates take
|
|
502
|
+
`slaDeadlineHours`, counted through a working-hours calendar:
|
|
503
|
+
|
|
504
|
+
```ts
|
|
505
|
+
import { businessHoursCalendar } from 'hierarchical-approval';
|
|
506
|
+
|
|
507
|
+
const engine = new ApprovalEngine({
|
|
508
|
+
adapter,
|
|
509
|
+
calendar: businessHoursCalendar({ workdayStartHour: 9, workdayEndHour: 17 }),
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
// Submitted Friday 16:00, escalationAfterHours: 4 -> due Monday 12:00
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
Evenings, weekends and holidays are skipped, and a request arriving outside
|
|
516
|
+
working hours starts counting from the next working moment — so one submitted at
|
|
517
|
+
20:00 is not already overdue by morning.
|
|
518
|
+
|
|
519
|
+
`weekendCalendar` knows whole days only. Give it an hour-based deadline and the
|
|
520
|
+
engine falls back to **elapsed clock time**, rather than quietly pretending the
|
|
521
|
+
calendar applied; use `businessHoursCalendar` when hours should skip
|
|
522
|
+
non-working time. Days and hours are mutually exclusive on the same level or
|
|
523
|
+
template, and `validateTemplate()` rejects setting both.
|
|
524
|
+
|
|
471
525
|
### Retention
|
|
472
526
|
|
|
473
527
|
Approval tables only grow, and data-minimisation rules eventually require old
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { I as IStorageAdapter, P as PaginationOpts, a as PaginatedResult, b as InstanceFilter, C as CursorPaginationOpts, c as CursorPaginatedResult } from './IStorageAdapter-
|
|
2
|
-
import { l as ConditionExpression,
|
|
3
|
-
import { I as INotificationAdapter, b as ApprovalEventName, a as ApprovalEventMap } from './INotificationAdapter-
|
|
1
|
+
import { I as IStorageAdapter, P as PaginationOpts, a as PaginatedResult, b as InstanceFilter, C as CursorPaginationOpts, c as CursorPaginatedResult } from './IStorageAdapter-yX9ERfQE.cjs';
|
|
2
|
+
import { l as ConditionExpression, q as ResolverFn, g as ApprovalTemplateConfig, A as ApprovalTemplate, k as AuditContext, a as ApprovalInstance, e as ApprovalMode, b as AuditEntry } from './instance-weh2w7Ji.cjs';
|
|
3
|
+
import { I as INotificationAdapter, b as ApprovalEventName, a as ApprovalEventMap } from './INotificationAdapter-C6HPrzh6.cjs';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import { L as Logger } from './Logger-BplhlU7l.cjs';
|
|
6
6
|
import { C as Clock } from './Clock-3FnOczFJ.cjs';
|
|
7
|
-
import { I as IOperationMiddleware, a as ApprovalError } from './IOperationMiddleware-
|
|
8
|
-
import { I as IAuditAdapter } from './IAuditAdapter-
|
|
7
|
+
import { I as IOperationMiddleware, a as ApprovalError } from './IOperationMiddleware-CxnPzpqL.cjs';
|
|
8
|
+
import { I as IAuditAdapter } from './IAuditAdapter-2UU5edKG.cjs';
|
|
9
9
|
import { I as IMetricsAdapter } from './IMetricsAdapter-DWq8IFaf.cjs';
|
|
10
10
|
import { I as ISchedulerAdapter } from './ISchedulerAdapter-DKv_QjVN.cjs';
|
|
11
|
-
import { I as IAuthorizationPolicy } from './IAuthorizationPolicy-
|
|
11
|
+
import { I as IAuthorizationPolicy } from './IAuthorizationPolicy-DPpiKzyh.cjs';
|
|
12
12
|
|
|
13
13
|
declare const SubmitOptionsSchema: z.ZodObject<{
|
|
14
14
|
templateName: z.ZodString;
|
|
@@ -141,6 +141,16 @@ interface BusinessCalendar {
|
|
|
141
141
|
* elapsed clock time within the resulting business day.
|
|
142
142
|
*/
|
|
143
143
|
addBusinessDays(from: Date, days: number): Date;
|
|
144
|
+
/**
|
|
145
|
+
* Return the date that is `hours` **working** hours after `from`, skipping
|
|
146
|
+
* non-working hours, weekends and holidays.
|
|
147
|
+
*
|
|
148
|
+
* Optional. A calendar that only knows about whole days — such as
|
|
149
|
+
* {@link weekendCalendar} — omits it, and the engine falls back to elapsed
|
|
150
|
+
* clock time for any hour-based deadline rather than silently pretending the
|
|
151
|
+
* calendar was applied.
|
|
152
|
+
*/
|
|
153
|
+
addBusinessHours?(from: Date, hours: number): Date;
|
|
144
154
|
}
|
|
145
155
|
interface WeekendCalendarOptions {
|
|
146
156
|
/** Dates to treat as non-working days (compared by local calendar date). */
|
|
@@ -157,6 +167,37 @@ interface WeekendCalendarOptions {
|
|
|
157
167
|
* holidays. Day arithmetic is performed in the host's local timezone.
|
|
158
168
|
*/
|
|
159
169
|
declare function weekendCalendar(options?: WeekendCalendarOptions): BusinessCalendar;
|
|
170
|
+
interface BusinessHoursCalendarOptions extends WeekendCalendarOptions {
|
|
171
|
+
/** First working hour of the day, 0-23 in local time. Defaults to 9. */
|
|
172
|
+
workdayStartHour?: number;
|
|
173
|
+
/**
|
|
174
|
+
* Hour at which the working day ends, 0-24 in local time. Defaults to 17.
|
|
175
|
+
* Must be greater than {@link workdayStartHour}.
|
|
176
|
+
*/
|
|
177
|
+
workdayEndHour?: number;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* A calendar that counts only working hours within working days.
|
|
181
|
+
*
|
|
182
|
+
* SLAs in an ERP are quoted in hours far more often than days — "respond within
|
|
183
|
+
* four working hours" — and counting those as elapsed clock time makes a
|
|
184
|
+
* request submitted at 16:00 on a Friday overdue before anybody could have
|
|
185
|
+
* looked at it. This advances the clock only through the configured working
|
|
186
|
+
* window, skipping evenings, weekends and holidays.
|
|
187
|
+
*
|
|
188
|
+
* A `from` outside working hours is first moved forward to the next working
|
|
189
|
+
* moment, so a deadline never starts counting from a time nobody was at work.
|
|
190
|
+
*
|
|
191
|
+
* Arithmetic is performed in the host's local timezone, matching
|
|
192
|
+
* {@link weekendCalendar}.
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```ts
|
|
196
|
+
* const calendar = businessHoursCalendar({ workdayStartHour: 9, workdayEndHour: 17 });
|
|
197
|
+
* // Friday 16:00 + 4 working hours -> Monday 12:00
|
|
198
|
+
* ```
|
|
199
|
+
*/
|
|
200
|
+
declare function businessHoursCalendar(options?: BusinessHoursCalendarOptions): Required<Pick<BusinessCalendar, 'addBusinessDays' | 'addBusinessHours'>>;
|
|
160
201
|
|
|
161
202
|
type IdGeneratorPrefix = 'inst' | 'tpl' | 'att';
|
|
162
203
|
type IdGeneratorFn = (prefix: IdGeneratorPrefix) => string;
|
|
@@ -800,6 +841,39 @@ declare class ApprovalEngine {
|
|
|
800
841
|
private withOptimisticRetry;
|
|
801
842
|
/** Compute a deadline `days` from `from`, honouring the business calendar if one is configured. */
|
|
802
843
|
private deadlineFrom;
|
|
844
|
+
/**
|
|
845
|
+
* Resolve an hour-based deadline.
|
|
846
|
+
*
|
|
847
|
+
* A calendar that only knows whole days — `weekendCalendar`, say — has no
|
|
848
|
+
* `addBusinessHours`, and this falls back to elapsed clock time rather than
|
|
849
|
+
* quietly pretending the calendar was applied. Configure
|
|
850
|
+
* `businessHoursCalendar` to have hours skip evenings and weekends.
|
|
851
|
+
*/
|
|
852
|
+
private deadlineFromHours;
|
|
853
|
+
/** Level deadline from whichever of days/hours the template configured. */
|
|
854
|
+
private levelEscalationDue;
|
|
855
|
+
/** First rung of a ladder, sorted by delay, or undefined when there is none. */
|
|
856
|
+
private firstRungOf;
|
|
857
|
+
/**
|
|
858
|
+
* The escalation ladder for an instance, sorted by delay.
|
|
859
|
+
*
|
|
860
|
+
* Read from the instance's template snapshot so an in-flight approval keeps
|
|
861
|
+
* the ladder it was submitted under, exactly as the single-step
|
|
862
|
+
* {@link EscalationConfig} already did.
|
|
863
|
+
*/
|
|
864
|
+
private escalationLadder;
|
|
865
|
+
/**
|
|
866
|
+
* When a level started collecting decisions.
|
|
867
|
+
*
|
|
868
|
+
* Escalation rungs are measured from this, not from the previous rung, so a
|
|
869
|
+
* ladder reads the way it is written. Recovered from the audit trail — the
|
|
870
|
+
* `submitted` entry for the opening level, the `level_advanced` entry
|
|
871
|
+
* otherwise — and falls back to `now` when no entry exists, which only leaves
|
|
872
|
+
* the ladder no worse off than the single-step behaviour it replaces.
|
|
873
|
+
*/
|
|
874
|
+
private levelOpenedAt;
|
|
875
|
+
/** Deadline for one rung, measured from when the level opened. */
|
|
876
|
+
private stepDueAt;
|
|
803
877
|
private requireInstance;
|
|
804
878
|
/**
|
|
805
879
|
* Identity of the parallel branch group a level belongs to.
|
|
@@ -890,4 +964,4 @@ declare class ApprovalEngine {
|
|
|
890
964
|
private runExternalAudit;
|
|
891
965
|
}
|
|
892
966
|
|
|
893
|
-
export { type AddCommentOptions as A, type BulkResult as B, type CanApproveResult as C, type DelegateOptions as D, type EscalateOptions as E,
|
|
967
|
+
export { type AddCommentOptions as A, type BulkResult as B, type CanApproveResult as C, type DelegateOptions as D, type EscalateOptions as E, toComparableNumber as F, validateConditionExpression as G, type HealthResult as H, type IdGeneratorFn as I, weekendCalendar as J, type OrgProvider as O, type PreviewChainLevel as P, type ReassignOptions as R, type SubmitOptions as S, TEMPLATE_BUNDLE_VERSION as T, type UpdateDataOptions as U, type ValidationResult as V, type WeekendCalendarOptions as W, ApprovalEngine as a, type ApprovalEngineOptions as b, type ApprovalStatistics as c, type ApproveOptions as d, type ApproverResolverFn as e, type ApproverWorkload as f, type BusinessCalendar as g, type BusinessHoursCalendarOptions as h, type CancelOptions as i, type ConditionOperatorFn as j, type CycleTimeStats as k, type IdempotencyKeyFn as l, type ImportResult as m, type OutOfOfficeProvider as n, type OverrideOptions as o, type PreviewResult as p, type ProvideInfoOptions as q, type PurgeResult as r, type RejectOptions as s, type RequestInfoOptions as t, type ResubmitOptions as u, type RetryPolicy as v, type TemplateBundle as w, type TransferResult as x, businessHoursCalendar as y, defaultIdGenerator as z };
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { I as IStorageAdapter, P as PaginationOpts, a as PaginatedResult, b as InstanceFilter, C as CursorPaginationOpts, c as CursorPaginatedResult } from './IStorageAdapter-
|
|
2
|
-
import { l as ConditionExpression,
|
|
3
|
-
import { I as INotificationAdapter, b as ApprovalEventName, a as ApprovalEventMap } from './INotificationAdapter-
|
|
1
|
+
import { I as IStorageAdapter, P as PaginationOpts, a as PaginatedResult, b as InstanceFilter, C as CursorPaginationOpts, c as CursorPaginatedResult } from './IStorageAdapter-ChPT7ZDp.js';
|
|
2
|
+
import { l as ConditionExpression, q as ResolverFn, g as ApprovalTemplateConfig, A as ApprovalTemplate, k as AuditContext, a as ApprovalInstance, e as ApprovalMode, b as AuditEntry } from './instance-weh2w7Ji.js';
|
|
3
|
+
import { I as INotificationAdapter, b as ApprovalEventName, a as ApprovalEventMap } from './INotificationAdapter-BNGivLgU.js';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import { L as Logger } from './Logger-BplhlU7l.js';
|
|
6
6
|
import { C as Clock } from './Clock-3FnOczFJ.js';
|
|
7
|
-
import { I as IOperationMiddleware, a as ApprovalError } from './IOperationMiddleware-
|
|
8
|
-
import { I as IAuditAdapter } from './IAuditAdapter-
|
|
7
|
+
import { I as IOperationMiddleware, a as ApprovalError } from './IOperationMiddleware-CXtg2wzF.js';
|
|
8
|
+
import { I as IAuditAdapter } from './IAuditAdapter-DSor54iY.js';
|
|
9
9
|
import { I as IMetricsAdapter } from './IMetricsAdapter-DWq8IFaf.js';
|
|
10
10
|
import { I as ISchedulerAdapter } from './ISchedulerAdapter-DKv_QjVN.js';
|
|
11
|
-
import { I as IAuthorizationPolicy } from './IAuthorizationPolicy-
|
|
11
|
+
import { I as IAuthorizationPolicy } from './IAuthorizationPolicy-BOWg-3AH.js';
|
|
12
12
|
|
|
13
13
|
declare const SubmitOptionsSchema: z.ZodObject<{
|
|
14
14
|
templateName: z.ZodString;
|
|
@@ -141,6 +141,16 @@ interface BusinessCalendar {
|
|
|
141
141
|
* elapsed clock time within the resulting business day.
|
|
142
142
|
*/
|
|
143
143
|
addBusinessDays(from: Date, days: number): Date;
|
|
144
|
+
/**
|
|
145
|
+
* Return the date that is `hours` **working** hours after `from`, skipping
|
|
146
|
+
* non-working hours, weekends and holidays.
|
|
147
|
+
*
|
|
148
|
+
* Optional. A calendar that only knows about whole days — such as
|
|
149
|
+
* {@link weekendCalendar} — omits it, and the engine falls back to elapsed
|
|
150
|
+
* clock time for any hour-based deadline rather than silently pretending the
|
|
151
|
+
* calendar was applied.
|
|
152
|
+
*/
|
|
153
|
+
addBusinessHours?(from: Date, hours: number): Date;
|
|
144
154
|
}
|
|
145
155
|
interface WeekendCalendarOptions {
|
|
146
156
|
/** Dates to treat as non-working days (compared by local calendar date). */
|
|
@@ -157,6 +167,37 @@ interface WeekendCalendarOptions {
|
|
|
157
167
|
* holidays. Day arithmetic is performed in the host's local timezone.
|
|
158
168
|
*/
|
|
159
169
|
declare function weekendCalendar(options?: WeekendCalendarOptions): BusinessCalendar;
|
|
170
|
+
interface BusinessHoursCalendarOptions extends WeekendCalendarOptions {
|
|
171
|
+
/** First working hour of the day, 0-23 in local time. Defaults to 9. */
|
|
172
|
+
workdayStartHour?: number;
|
|
173
|
+
/**
|
|
174
|
+
* Hour at which the working day ends, 0-24 in local time. Defaults to 17.
|
|
175
|
+
* Must be greater than {@link workdayStartHour}.
|
|
176
|
+
*/
|
|
177
|
+
workdayEndHour?: number;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* A calendar that counts only working hours within working days.
|
|
181
|
+
*
|
|
182
|
+
* SLAs in an ERP are quoted in hours far more often than days — "respond within
|
|
183
|
+
* four working hours" — and counting those as elapsed clock time makes a
|
|
184
|
+
* request submitted at 16:00 on a Friday overdue before anybody could have
|
|
185
|
+
* looked at it. This advances the clock only through the configured working
|
|
186
|
+
* window, skipping evenings, weekends and holidays.
|
|
187
|
+
*
|
|
188
|
+
* A `from` outside working hours is first moved forward to the next working
|
|
189
|
+
* moment, so a deadline never starts counting from a time nobody was at work.
|
|
190
|
+
*
|
|
191
|
+
* Arithmetic is performed in the host's local timezone, matching
|
|
192
|
+
* {@link weekendCalendar}.
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```ts
|
|
196
|
+
* const calendar = businessHoursCalendar({ workdayStartHour: 9, workdayEndHour: 17 });
|
|
197
|
+
* // Friday 16:00 + 4 working hours -> Monday 12:00
|
|
198
|
+
* ```
|
|
199
|
+
*/
|
|
200
|
+
declare function businessHoursCalendar(options?: BusinessHoursCalendarOptions): Required<Pick<BusinessCalendar, 'addBusinessDays' | 'addBusinessHours'>>;
|
|
160
201
|
|
|
161
202
|
type IdGeneratorPrefix = 'inst' | 'tpl' | 'att';
|
|
162
203
|
type IdGeneratorFn = (prefix: IdGeneratorPrefix) => string;
|
|
@@ -800,6 +841,39 @@ declare class ApprovalEngine {
|
|
|
800
841
|
private withOptimisticRetry;
|
|
801
842
|
/** Compute a deadline `days` from `from`, honouring the business calendar if one is configured. */
|
|
802
843
|
private deadlineFrom;
|
|
844
|
+
/**
|
|
845
|
+
* Resolve an hour-based deadline.
|
|
846
|
+
*
|
|
847
|
+
* A calendar that only knows whole days — `weekendCalendar`, say — has no
|
|
848
|
+
* `addBusinessHours`, and this falls back to elapsed clock time rather than
|
|
849
|
+
* quietly pretending the calendar was applied. Configure
|
|
850
|
+
* `businessHoursCalendar` to have hours skip evenings and weekends.
|
|
851
|
+
*/
|
|
852
|
+
private deadlineFromHours;
|
|
853
|
+
/** Level deadline from whichever of days/hours the template configured. */
|
|
854
|
+
private levelEscalationDue;
|
|
855
|
+
/** First rung of a ladder, sorted by delay, or undefined when there is none. */
|
|
856
|
+
private firstRungOf;
|
|
857
|
+
/**
|
|
858
|
+
* The escalation ladder for an instance, sorted by delay.
|
|
859
|
+
*
|
|
860
|
+
* Read from the instance's template snapshot so an in-flight approval keeps
|
|
861
|
+
* the ladder it was submitted under, exactly as the single-step
|
|
862
|
+
* {@link EscalationConfig} already did.
|
|
863
|
+
*/
|
|
864
|
+
private escalationLadder;
|
|
865
|
+
/**
|
|
866
|
+
* When a level started collecting decisions.
|
|
867
|
+
*
|
|
868
|
+
* Escalation rungs are measured from this, not from the previous rung, so a
|
|
869
|
+
* ladder reads the way it is written. Recovered from the audit trail — the
|
|
870
|
+
* `submitted` entry for the opening level, the `level_advanced` entry
|
|
871
|
+
* otherwise — and falls back to `now` when no entry exists, which only leaves
|
|
872
|
+
* the ladder no worse off than the single-step behaviour it replaces.
|
|
873
|
+
*/
|
|
874
|
+
private levelOpenedAt;
|
|
875
|
+
/** Deadline for one rung, measured from when the level opened. */
|
|
876
|
+
private stepDueAt;
|
|
803
877
|
private requireInstance;
|
|
804
878
|
/**
|
|
805
879
|
* Identity of the parallel branch group a level belongs to.
|
|
@@ -890,4 +964,4 @@ declare class ApprovalEngine {
|
|
|
890
964
|
private runExternalAudit;
|
|
891
965
|
}
|
|
892
966
|
|
|
893
|
-
export { type AddCommentOptions as A, type BulkResult as B, type CanApproveResult as C, type DelegateOptions as D, type EscalateOptions as E,
|
|
967
|
+
export { type AddCommentOptions as A, type BulkResult as B, type CanApproveResult as C, type DelegateOptions as D, type EscalateOptions as E, toComparableNumber as F, validateConditionExpression as G, type HealthResult as H, type IdGeneratorFn as I, weekendCalendar as J, type OrgProvider as O, type PreviewChainLevel as P, type ReassignOptions as R, type SubmitOptions as S, TEMPLATE_BUNDLE_VERSION as T, type UpdateDataOptions as U, type ValidationResult as V, type WeekendCalendarOptions as W, ApprovalEngine as a, type ApprovalEngineOptions as b, type ApprovalStatistics as c, type ApproveOptions as d, type ApproverResolverFn as e, type ApproverWorkload as f, type BusinessCalendar as g, type BusinessHoursCalendarOptions as h, type CancelOptions as i, type ConditionOperatorFn as j, type CycleTimeStats as k, type IdempotencyKeyFn as l, type ImportResult as m, type OutOfOfficeProvider as n, type OverrideOptions as o, type PreviewResult as p, type ProvideInfoOptions as q, type PurgeResult as r, type RejectOptions as s, type RequestInfoOptions as t, type ResubmitOptions as u, type RetryPolicy as v, type TemplateBundle as w, type TransferResult as x, businessHoursCalendar as y, defaultIdGenerator as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as ApprovalInstance, d as ApprovalLevelInstance } from './instance-
|
|
1
|
+
import { a as ApprovalInstance, d as ApprovalLevelInstance } from './instance-weh2w7Ji.js';
|
|
2
2
|
|
|
3
3
|
interface AuthorizationContext {
|
|
4
4
|
operation: 'submit' | 'approve' | 'reject' | 'delegate' | 'reassign' | 'cancel' | 'escalate' | 'override' | 'resubmit' | 'addComment' | 'updateData' | 'requestInfo' | 'provideInfo' | 'addAttachment' | 'removeAttachment';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as ApprovalInstance, d as ApprovalLevelInstance } from './instance-
|
|
1
|
+
import { a as ApprovalInstance, d as ApprovalLevelInstance } from './instance-weh2w7Ji.cjs';
|
|
2
2
|
|
|
3
3
|
interface AuthorizationContext {
|
|
4
4
|
operation: 'submit' | 'approve' | 'reject' | 'delegate' | 'reassign' | 'cancel' | 'escalate' | 'override' | 'resubmit' | 'addComment' | 'updateData' | 'requestInfo' | 'provideInfo' | 'addAttachment' | 'removeAttachment';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as ApprovalTemplate, a as ApprovalInstance, f as ApprovalStatus, b as AuditEntry } from './instance-
|
|
1
|
+
import { A as ApprovalTemplate, a as ApprovalInstance, f as ApprovalStatus, b as AuditEntry } from './instance-weh2w7Ji.js';
|
|
2
2
|
|
|
3
3
|
interface PaginationOpts {
|
|
4
4
|
limit: number;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as ApprovalTemplate, a as ApprovalInstance, f as ApprovalStatus, b as AuditEntry } from './instance-
|
|
1
|
+
import { A as ApprovalTemplate, a as ApprovalInstance, f as ApprovalStatus, b as AuditEntry } from './instance-weh2w7Ji.cjs';
|
|
2
2
|
|
|
3
3
|
interface PaginationOpts {
|
|
4
4
|
limit: number;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { I as IStorageAdapter, P as PaginationOpts, a as PaginatedResult, b as InstanceFilter, C as CursorPaginationOpts, c as CursorPaginatedResult } from '../IStorageAdapter-
|
|
2
|
-
import { A as ApprovalTemplate, a as ApprovalInstance, b as AuditEntry } from '../instance-
|
|
1
|
+
import { I as IStorageAdapter, P as PaginationOpts, a as PaginatedResult, b as InstanceFilter, C as CursorPaginationOpts, c as CursorPaginatedResult } from '../IStorageAdapter-yX9ERfQE.cjs';
|
|
2
|
+
import { A as ApprovalTemplate, a as ApprovalInstance, b as AuditEntry } from '../instance-weh2w7Ji.cjs';
|
|
3
3
|
|
|
4
4
|
declare class MemoryAdapter implements IStorageAdapter {
|
|
5
5
|
private templates;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { I as IStorageAdapter, P as PaginationOpts, a as PaginatedResult, b as InstanceFilter, C as CursorPaginationOpts, c as CursorPaginatedResult } from '../IStorageAdapter-
|
|
2
|
-
import { A as ApprovalTemplate, a as ApprovalInstance, b as AuditEntry } from '../instance-
|
|
1
|
+
import { I as IStorageAdapter, P as PaginationOpts, a as PaginatedResult, b as InstanceFilter, C as CursorPaginationOpts, c as CursorPaginatedResult } from '../IStorageAdapter-ChPT7ZDp.js';
|
|
2
|
+
import { A as ApprovalTemplate, a as ApprovalInstance, b as AuditEntry } from '../instance-weh2w7Ji.js';
|
|
3
3
|
|
|
4
4
|
declare class MemoryAdapter implements IStorageAdapter {
|
|
5
5
|
private templates;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as tls from 'tls';
|
|
2
2
|
import * as pg from 'pg';
|
|
3
|
-
import { I as IStorageAdapter, P as PaginationOpts, a as PaginatedResult, b as InstanceFilter, C as CursorPaginationOpts, c as CursorPaginatedResult } from '../IStorageAdapter-
|
|
4
|
-
import { A as ApprovalTemplate, a as ApprovalInstance, b as AuditEntry } from '../instance-
|
|
3
|
+
import { I as IStorageAdapter, P as PaginationOpts, a as PaginatedResult, b as InstanceFilter, C as CursorPaginationOpts, c as CursorPaginatedResult } from '../IStorageAdapter-yX9ERfQE.cjs';
|
|
4
|
+
import { A as ApprovalTemplate, a as ApprovalInstance, b as AuditEntry } from '../instance-weh2w7Ji.cjs';
|
|
5
5
|
|
|
6
6
|
interface PostgresAdapterOptions {
|
|
7
7
|
connectionString?: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as tls from 'tls';
|
|
2
2
|
import * as pg from 'pg';
|
|
3
|
-
import { I as IStorageAdapter, P as PaginationOpts, a as PaginatedResult, b as InstanceFilter, C as CursorPaginationOpts, c as CursorPaginatedResult } from '../IStorageAdapter-
|
|
4
|
-
import { A as ApprovalTemplate, a as ApprovalInstance, b as AuditEntry } from '../instance-
|
|
3
|
+
import { I as IStorageAdapter, P as PaginationOpts, a as PaginatedResult, b as InstanceFilter, C as CursorPaginationOpts, c as CursorPaginatedResult } from '../IStorageAdapter-ChPT7ZDp.js';
|
|
4
|
+
import { A as ApprovalTemplate, a as ApprovalInstance, b as AuditEntry } from '../instance-weh2w7Ji.js';
|
|
5
5
|
|
|
6
6
|
interface PostgresAdapterOptions {
|
|
7
7
|
connectionString?: string;
|